简体   繁体   English

.Net 2+:为什么 if( 1 == null ) 不再引发编译器异常?

[英].Net 2+: why does if( 1 == null ) no longer throw a compiler exception?

I'm using int as an example, but this applies to any value type in.Net我以int为例,但这适用于.Net 中的任何值类型

In.Net 1 the following would throw a compiler exception:在.Net 1 中,以下会引发编译器异常:

int i = SomeFunctionThatReturnsInt();

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

Now (in.Net 2 or 3.5) that exception has gone.现在(in.Net 2 或 3.5)该异常已经消失。

I know why this is:我知道这是为什么:

int? j = null; //nullable int

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

The problem is that because int?问题是因为int? is nullable and int now has a implicit cast to int?可以为空并且int现在隐式转换为int? . . The syntax above is compiler magic.上面的语法是编译器的魔法。 Really we're doing:我们真的在做:

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)

So now, when we do i == null we get:所以现在,当我们执行i == null时,我们得到:

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

Given that C# is doing compiler logic to calculate this anyway why can't it be smart enough to not do it when dealing with absolute values like null ?鉴于 C# 正在执行编译器逻辑来计算这个,为什么在处理像null这样的绝对值时不能聪明到不这样做?

Odd... compiling this with VS2008, targetting .NET 3.5:奇怪......用VS2008编译这个,针对.NET 3.5:

static int F()
{
    return 42;
}

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

    if (i == null)
    {
    }
}

I get a compiler warning我收到编译器警告

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

And it generates the following IL... which presumably the JIT will optimize away它会生成以下 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

Can you post a code snippet?你能发布一个代码片段吗?

I don't think this is a compiler problem per se ;我认为这本身不是编译器问题; an integer value is never null, but the idea of equating them isn't invalid; integer 值永远不会是 null,但将它们等同起来的想法并非无效; it's a valid function that always returns false.这是一个有效的 function 总是返回 false。 And the compiler knows;编译器知道; the code编码

bool oneIsNull = 1 == null;

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

So if you want the compiler error back, go to the project properties and turn on 'treat warnings as errors' for this error, and you'll start seeing them as build-breaking problems again.因此,如果您想要返回编译器错误,go 到项目属性并为此错误打开“将警告视为错误”,您将再次开始将它们视为构建中断问题。

Compiler still generates warning when you compare non-nullable type to null, which is just the way it should be.当您将不可为空的类型与 null 进行比较时,编译器仍然会生成警告,这正是它应该的方式。 May be your warning level is too low or this was changed in recent versions (I only did that in .net 3.5).可能是您的警告级别太低或在最近的版本中已更改(我仅在 .net 3.5 中这样做)。

The 2.0 framework introduced the nullable value type. 2.0 框架引入了可空值类型。 Even though the literal constant "1" can never be null, its underlying type (int) can now be cast to a Nullable int type.即使字面常量“1”永远不可能是 null,它的基础类型 (int) 现在可以转换为 Nullable int 类型。 My guess is that the compiler can no longer assume that int types are not nullable, even when it is a literal constant.我的猜测是编译器不能再假设 int 类型不可为空,即使它是一个字面常量。 I do get a warning when compiling 2.0:编译 2.0 时确实收到警告:

Warning 1 The result of the expression is always 'false' since a value of type 'int' is never equal to 'null' of type 'int?'警告 1 表达式的结果始终为“假”,因为“int”类型的值永远不会等于“int?”类型的“null”。

The warning is new (3.5 I think) - the error is the same as if I'd done 1 == 2 , which it's smart enough to spot as never true.警告是新的(我认为是 3.5) - 错误与我所做的1 == 2相同,它足够聪明,可以发现它永远不会正确。

I suspect that with full 3.5 optimisations the whole statement will just be stripped out, as it's pretty smart with never true evaluations.我怀疑通过完整的 3.5 优化,整个语句将被删除,因为它非常聪明,从来没有真正的评估。

While I might want 1==2 to compile (to switch off a function block while I test something else for instance) I don't want 1==null to.虽然我可能希望1==2编译(例如,在我测试其他东西时关闭 function 块)我不希望1==null

It ought to be a compile-time error, because the types are incompatible (value types can never be null).这应该是编译时错误,因为类型不兼容(值类型永远不能为空)。 It's pretty sad that it isn't.很遗憾,事实并非如此。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM