为什么不递增Nullable <int>抛出异常?

FSo*_*ou1 97 .net c# nullable

你能解释一下,为什么Console.WriteLine写空行(Console.WriteLine(null)给我编译错误)以及为什么没有NullReferenceException(甚至a+=1不应该提高它)?

int? a = null;
a++; // Why there is not NullReferenceException? 
Console.WriteLine(a); // Empty line
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 122

你正在观察一个提升的操作员的影响.

从C#5规范的7.3.7节:

提升的运算符允许在非可空值类型上运行的预定义和用户定义的运算符也可以与这些类型的可空形式一起使用.提升运算符由满足特定要求的预定义和用户定义的运算符构成,如下所述:

  • 对于一元运算+ ++ - -- ! ~ 符,如果操作数和结果类型都是非可空值类型,则存在提升形式的运算符.通过向?操作数和结果类型添加单个修饰符来构造提升形式.如果操作数为null,则提升的运算符将生成空值.否则,提升的运算符解包操作数,应用基础运算符,并包装结果.

所以基本上,a++在这种情况下是一个带有null(作为int?)结果的表达式,并且该变量保持不变.

你打电话的时候

Console.WriteLine(a);
Run Code Online (Sandbox Code Playgroud)

正在装箱object,将其转换为空引用,打印为空行.

  • 在这里,我想我知道有关C#的所有信息!从来没有听说过这个. (5认同)
  • @Cole Johnson:Console.WriteLine(a ??"null"); :) (4认同)
  • 有没有办法打印"null"而不使用`Console.WriteLine(a == null?"null":a)`? (3认同)
  • @DavidChappelle当`a`的类型为`int?`时,我会说`a ?? ?? "null"`找不到两个操作数的通用类型.你需要一个暗示`object`是常见的类型.因此,将任一操作数转换为该值."a"将被装箱.例如`((对象)a)?? "null"`或`a ?? (对象) "空"`. (2认同)

Eri*_*ert 115

Jon的回答是正确的,但我会添加一些额外的注释.

为什么会Console.WriteLine(null)出现编译错误?

有19个重载,Console.WriteLine其中三个适用于null:a取一个string,取一个取一个char[]取一个object.C#无法确定这三个中的哪一个,所以它给出了一个错误.Console.WriteLine((object)null)这是合法的,因为现在很清楚.

为什么Console.WriteLine(a)要写一个空行?

a是null int?.重载决策选择object方法的版本,因此将int?框装入空引用.所以这基本上是相同的Console.WriteLine((object)null),它写了一个空行.

为什么没有NullReferenceException增量?

您担心的空引用在哪里? a是一个null int?,它不是一个开头的引用类型!请记住,可空值类型是值类型,而不是引用类型,因此除非它们被装箱为引用类型,否则不要指望它们具有引用语义.此外没有拳击.