Visual Studio 为什么C#在使用Math.Min时试图将int?转换为byte?

bzzcjhmw  于 2023-04-22  发布在  C#
关注(0)|答案(2)|浏览(110)

我刚刚发现了这个有趣的问题:

int done = 50;
int? total = 100;

var perc = done * 100 / total; // No problem

// Error: Argument 2: cannot convert from 'int?' to 'byte'
// Argument 1 is still int32
var perc2 = Math.Min(100, done * 100 / total);

起初,我的代码只需要第一个perc。令人惊讶的是,那里没有错误,因为我错过了应该在那里的null检查。我直到后来才发现我的错误:
然后在某些情况下,估计值total比它应该的值小得多,但百分比需要限制在100,所以我添加了Math.Min。现在我发现我错过了一个空检查,错误消息有点误导。
这里发生了什么?C#在这种情况下试图做什么?

nukf8bse

nukf8bse1#

当你在代码中调用一个方法时,编译器会试图找到你传递的参数列表(如果有的话)提供的方法。

public static void M(int i) { }

你可以使用M(42)调用它,一切正常。当有多个候选者时:

public static void M(byte b) { }
public static void M(int i) { }

编译器将应用“重载解析”来确定“适用的函数成员”,并且当多个时,编译器将计算重载的“更好”以确定您打算调用的“更好的函数成员”。
在上面的例子M(42)中,选择int重载是因为C#中非后缀的数字字面量默认为int,所以M(int)是“更好”的重载。
(All“引号”中的部分可以在C#语言规范12.6.4重载解决方案中查找。
现在到你的代码。
假设文字100可以存储在byteint中(然后是一些),并且您的第二个参数不匹配任何一个重载,编译器不知道您打算调用哪个重载。
它必须选择任何一个来向您显示错误消息。在本例中,它似乎选择了声明顺序中的第一个。
给定此代码:

public static void Main()
{
    int? i = null;
    M(100, i);
}

public static void M(int i, int i2) {}
public static void M(byte b, byte b2) {}

其中提到:
无法从“int?”转换为“int”
如果我们交换方法声明:

public static void M(byte b, byte b2) {}
public static void M(int i, int i2) {}

它抱怨说:
无法从“int?”转换为“byte”

vm0i2vca

vm0i2vca2#

你正在使用一个Nullable类型。这是一种对不能为null的结构的 Package 。要获取值,你需要引用它:

var perc2 = Math.Min(100, done * 100 / total.Value);

相关问题