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

时间:2015-03-20 17:33:26

标签: c# .net nullable

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

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

3 个答案:

答案 0 :(得分:121)

您正在观察解除操作员的影响。

来自C#5规范的第7.3.7节:

  

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

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

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

致电时

Console.WriteLine(a);

object装箱,将其转换为空引用,并将其打印为空行。

答案 1 :(得分:115)

Jon的回答是正确的,但我会添加一些额外的注意事项。

  

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

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

  

为什么a写一个空行?

int?为空object。重载决策选择方法的int?版本,因此Console.WriteLine((object)null)被装箱为空引用。所以这与NullReferenceException基本相同,后者写一个空行。

  

为什么增量上没有a

您担心的空参考在哪里? int?是一个空{{1}},它不是一个开头的引用类型!请记住,可空值类型是值类型,而不是引用类型,因此除非将它们装箱为引用类型,否则不要期望它们具有引用语义。此外没有拳击。

答案 2 :(得分:0)

  

你是否正在增加null ???

int? a = null;
a++;

此语句仅表示null++,即null + 1。

根据本文档,可以为空的类型可以表示其基础值类型的正确值范围,加上一个额外的空值。可以为Nullable,发音为“Nullable of Int32”,可以分配从-2147483648到2147483647的任何值。 ,或者可以为其指定空值

这里增加null,然后它将变为空值而不是0或任何其他整数。

  

为什么打印空白而不是错误?

当您打印具有空值的可空类型时,它会打印空白而不是错误,因为您正在打印变量,即内存位置的值。可能为null或任何整数。

但是当你尝试使用Console.WriteLine(null)打印null时,因为null不是变量,所以它不引用任何内存位置。因此它给出了错误"NullReferenceException"

  

那么如何使用Console.WriteLine(2); ??

打印任何整数

在这种情况下,2将在临时位置进入内存,指针指向该内存位置进行打印。