11
int foo;
int? bar;

if (bar != null)
{
    foo = bar; // does not compile
    foo = (int)bar; // compiles
    foo = bar.Value; // compiles
}

我早就知道第一句话是不正确的,但它一直困扰着我。我已经验证它bar不为空,那么为什么编译器会抱怨呢?

4

4 回答 4

21

比较只是说 - 不是null,编译器仍然使用类型来查看是否可以进行赋值。

即使没有空检查,以下也会编译。

foo = (int)bar; 
于 2013-05-22T12:59:32.130 回答
17

的类型bar仍然是int?,并且没有从int?to的隐式转换int

该条件不会改变后面代码的有效性。其他演员也是如此:

object x = ...;
if (x is string)
{
    string y = x; // This is still invalid
    string z = (string) x; // This is fine
} 

编译器很少使用一段代码的结果来影响另一段代码的有效性。再举一个例子:

bool condition = ...;
string x;
if (condition)
{
    x = "yes";
}
if (!condition)
{
    x = "no";
}
Console.WriteLine(x); // Invalid

最后一行无效,因为x仍未明确分配。我们知道,无论 的值是什么x,我们都会输入其中一个语句if体……但编译器不会试图弄清楚这一点。

尽管这看起来很愚蠢,但它使语言规则变得更加简单。

于 2013-05-22T13:00:56.273 回答
3

编译器只检查你的程序在语法上是否正确。它不关心你的空检查。

编译器发现您可能会丢失分配 int 的信息?到 int ,因此它抱怨。

于 2013-05-22T13:04:52.727 回答
1

想象一下:如果你有一个类型为 as 的成员变量Nullable<int>,它被多个线程访问会怎样。让我们看看你在这种情况下的代码。

if(foo != null)
{
    // expensive operation that takes time.
    // what if another thread as nulled foo in the meantime?
    int bar = foo;
}
于 2013-05-22T13:09:17.560 回答