5

int以示例为例,但这适用于 .Net 中的任何值类型

在 .Net 1 中,以下内容会引发编译器异常:

int i = SomeFunctionThatReturnsInt();

if( i == null ) //compiler exception here

现在(在 .Net 2 或 3.5 中)该异常已经消失。

我知道这是为什么:

int? j = null; //nullable int

if( i == j )   //this shouldn't throw an exception

问题是因为int?是可以为空的,int现在有一个隐式转换为int?. 上面的语法是编译器的魔法。我们真的在做:

Nullable<int> j = null; //nullable int

//compiler is smart enough to do this
if( (Nullable<int>) i == j)   

//and not this
if( i == (int) j)

所以现在,当我们这样做时,i == null我们得到:

if( (Nullable<int>) i == null )

鉴于 C# 正在执行编译器逻辑来计算这个,为什么在处理绝对值时不能足够聪明地不这样做null

4

6 回答 6

3

奇怪...用 VS2008 编译它,目标是 .NET 3.5:

static int F()
{
    return 42;
}

static void Main(string[] args)
{
    int i = F();

    if (i == null)
    {
    }
}

我收到编译器警告

warning CS0472: The result of the expression is always 'false' since a value of type 'int' is never equal to 'null' of type 'int?'

它会生成以下 IL ...大概 JIT 会优化掉

L_0001: call int32 ConsoleApplication1.Program::F()
L_0006: stloc.0 
L_0007: ldc.i4.0 
L_0008: ldc.i4.0 
L_0009: ceq 
L_000b: stloc.1 
L_000c: br.s L_000e

你可以发布一个代码片段吗?

于 2008-09-15T13:14:45.830 回答
3

我认为这本身不是编译器问题;整数值永远不会为空,但将它们等同的想法并非无效;这是一个始终返回 false 的有效函数。编译器知道;编码

bool oneIsNull = 1 == null;

编译,但给出编译器警告:The result of the expression is always 'false' since a value of type 'int' is never equal to 'null' of type '<null>'.

因此,如果您希望恢复编译器错误,请转到项目属性并为此错误打开“将警告视为错误”,您将再次开始将它们视为破坏构建的问题。

于 2008-09-15T13:18:08.973 回答
1

当您将不可为空的类型与 null 进行比较时,编译器仍然会生成警告,这正是它应该的方式。可能是您的警告级别太低,或者这在最近的版本中已更改(我只在 .net 3.5 中这样做)。

于 2008-09-15T13:13:40.793 回答
1

2.0 框架引入了可空值类型。即使字面常量“1”永远不能为 null,它的基础类型 (int) 现在可以转换为 Nullable int 类型。我的猜测是编译器不能再假设 int 类型不可为空,即使它是一个字面常量。编译 2.0 时确实收到警告:

警告 1 表达式的结果始终为“假”,因为“int”类型的值永远不会等于“int?”类型的“null”。

于 2008-09-15T14:19:26.563 回答
0

警告是新的(我认为是 3.5) - 错误与我已经完成的错误相同1 == 2,它足够聪明,可以发现它永远不会正确。

我怀疑通过完整的 3.5 优化,整个语句将被删除,因为它非常聪明,从来没有真正的评估。

虽然我可能想要1==2编译(例如在我测试其他东西时关闭功能块)但我不想编译1==null

于 2008-09-15T13:48:07.777 回答
0

这应该是编译时错误,因为类型不兼容(值类型永远不能为空)。很遗憾,事实并非如此。

于 2008-09-15T13:57:21.687 回答