我今天碰到了这个,并且不知道为什么C#编译器没有抛出错误.
Int32 x = 1;
if (x == null)
{
Console.WriteLine("What the?");
}
Run Code Online (Sandbox Code Playgroud)
我很困惑x怎么可能是null.特别是因为这个赋值肯定会抛出编译器错误:
Int32 x = null;
Run Code Online (Sandbox Code Playgroud)
是否有可能x变为null,微软是否决定不将此检查放入编译器,还是完全错过了?
更新:在编写了这篇文章的代码后,编译器突然发出一个警告,表达式永远不会成立.现在我真的迷路了.我把对象放到一个类中,现在警告已经消失,但是留下了问题,值类型最终是否为null.
public class Test
{
public DateTime ADate = DateTime.Now;
public Test ()
{
Test test = new Test();
if (test.ADate == null)
{
Console.WriteLine("What the?");
}
}
}
Run Code Online (Sandbox Code Playgroud)
Eri*_*ert 118
这是合法的,因为运算符重载决策具有唯一的最佳运算符可供选择.有一个==运算符,它有两个可空的整数.int local可以转换为可以为null的int.null文字可以转换为可以为null的int.因此,这是==运算符的合法用法,并且总是会导致错误.
同样,我们也允许你说"if(x == 12.6)",这也总是假的.int local可以转换为double,文字可以转换为double,显然它们永远不会相等.
Mar*_*ell 17
这不是错误,因为有一个(int?)转换; 它会在给出的示例中生成警告:
表达式的结果始终为"false",因为类型"int"的值永远不等于"int"类型的"null".
如果检查IL,您将看到它完全删除了无法访问的分支 - 它在发布版本中不存在.
但请注意,它不会为具有相等运算符的自定义结构生成此警告.它曾经用于2.0,但不是3.0编译器.代码仍然被删除(因此它知道代码无法访问),但不会生成警告:
using System;
struct MyValue
{
private readonly int value;
public MyValue(int value) { this.value = value; }
public static bool operator ==(MyValue x, MyValue y) {
return x.value == y.value;
}
public static bool operator !=(MyValue x, MyValue y) {
return x.value != y.value;
}
}
class Program
{
static void Main()
{
int i = 1;
MyValue v = new MyValue(1);
if (i == null) { Console.WriteLine("a"); } // warning
if (v == null) { Console.WriteLine("a"); } // no warning
}
}
Run Code Online (Sandbox Code Playgroud)
使用IL(for Main) - 注意除了(可能有副作用)之外的所有内容MyValue(1)都已被删除:
.method private hidebysig static void Main() cil managed
{
.entrypoint
.maxstack 2
.locals init (
[0] int32 i,
[1] valuetype MyValue v)
L_0000: ldc.i4.1
L_0001: stloc.0
L_0002: ldloca.s v
L_0004: ldc.i4.1
L_0005: call instance void MyValue::.ctor(int32)
L_000a: ret
}
Run Code Online (Sandbox Code Playgroud)
这基本上是:
private static void Main()
{
MyValue v = new MyValue(1);
}
Run Code Online (Sandbox Code Playgroud)