【问题标题】:Why is integer == null a valid boolean expression in C#?为什么整数 == null 在 C# 中是一个有效的布尔表达式?
【发布时间】:2013-06-15 07:05:55
【问题描述】:

如果integerint 类型的变量)不可为空,为什么 integer == null 在 C# 中是一个有效的布尔表达式? (我不反对,其实我很喜欢,但我不知道有可能)

【问题讨论】:

  • 您确实会收到警告,类似于“表达式总是错误的”。至于为什么允许,即不会导致编译时错误……我想这与允许这样做的原因相同; while(true)
  • C# 编译器将在编译时将其优化为在发布模式下编译时为 false(ldc.i4.0 最终在 IL 中)。

标签: c# null boolean non-nullable


【解决方案1】:

虽然int 本身不可为空,但存在到int? 的隐式转换, 可以为空。

此时,如果该结构声明了一个两边都具有相同类型的 == 运算符,那么它也可以用于可空类型。

所以这不会编译:

public struct Foo {}

class Test
{
    static void Main()
    {
        Foo x = new Foo();
        if (x == null)
        {
            ...
        }
    }
}

...但是如果你给Foo 一些运算符,它确实编译,并且没有警告:

public struct Foo
{
    public static bool operator ==(Foo x, Foo y) { return true; }
    public static bool operator !=(Foo x, Foo y) { return false; }
    public override bool Equals(object x) { return false; }
    public override int GetHashCode() { return 0; }
}

运算符调用不包含在编译代码中,因为编译器知道 RHS 为空。

因此,上述形式的代码(其中Foo 可以替换为任何不可为空的struct)在 MS C# 5 编译器中具有以下三种结果之一:

  • 警告 CS0472(例如 int
  • 错误 CS0019(自定义类型不会重载 ==
  • 干净编译(重载==的自定义类型,包括GuidDateTime

我不清楚为什么编译器会以不同于普通结构的方式处理某些“已知”类型。编辑:正如 Eric 在 cmets 中所指出的,这是 C# 编译器中的一个已知错误,希望在 Roslyn 中得到修复。

【讨论】:

  • 妈的,太奇怪了!也许结构是例外?
  • 并尝试创建自己的隐式运算符以将其转换为Nullable<T>(例如public static implicit operator Nullable<Foo>(Foo f))失败并出现编译器错误CS0555
  • 回复:尚不清楚为什么已知类型与用户定义类型不同:这是一个错误,可能是我在 C# 3.0 期间重构部分编译器时引入的。由于某些不清楚的原因,该错误从未得到修复,即使我们已经知道很长时间了。我似乎记得我在离开之前在罗斯林修好了它,但我不记得了。
  • 而这个也有一些类似的分析:stackoverflow.com/questions/2464097/…
【解决方案2】:

正如 Ed 提到的,有一个警告,但警告暗示了原因:int 可以自动转换为 int?,而nullint? 类型变量的有效值。

【讨论】:

  • skeet 秒杀我。该死的飞碟!
  • 你说反了。您的意思是说int 可以隐式转换int?
  • 确认。谢谢埃里克。已更正。
猜你喜欢
  • 2021-12-28
  • 1970-01-01
  • 1970-01-01
  • 2021-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-25
相关资源
最近更新 更多