代码之家  ›  专栏  ›  技术社区  ›  newdayrising

为什么不尝试向空值添加引发InvalidOperationException?

  •  8
  • newdayrising  · 技术社区  · 15 年前
    int? x = null;
    x = x + 1;  // Works, but x remains null
    

    我希望编译器尝试将x强制转换为int,但显然不是这样。

    280Z28编辑:更改 NullReferenceException InvalidOperationException 这是什么 Nullable<T>.Value 投掷当 HasValue 是假的。

    7 回复  |  直到 14 年前
        1
  •  10
  •   jason    15 年前

    这符合提升二进制运算符的规范。从7.7.2.7

    对于二进制运算符

    + - * / % & | ^ << >>

    如果操作数和结果类型都是不可为空的值类型,则存在运算符的提升形式。提升模板是通过添加一个 ? 对每个操作数和结果类型的修饰符。 如果一个或两个操作数都为空,则提升运算符将生成空值。 (bool的&and运算符除外?类型,如第7.10.3节所述)。否则,提升运算符将展开操作数,应用基础运算符,并包装结果。

    理由是:你应该考虑 null 对于一个可以为空的类型,意思是“我不知道值是什么”。“我不知道”加上一个的结果是什么?我不知道。”因此,结果应该是 无效的 .

        2
  •  5
  •   rusty    15 年前

    空值实际上从来不是空引用。它们总是对象引用。它们的内部类重写 == = 运算符。如果将它们与空进行比较,它们将返回 HasValue 属性。

        3
  •  2
  •   Barracoder    15 年前

    当您声明编译器可以为空时,为什么您希望它强制转换为int?编译器正在按照您告诉它的方式进行操作,NULL+1=NULL。

    在尝试添加int之前,必须显式强制转换或检查x.hasValue。

        4
  •  2
  •   Lee    15 年前

    原因是编译器为可为空类型创建了一个“lifted”运算符-在这种情况下,它类似于:

    public static int? operator +(int? a, int? b)
    {
        return (a == null || b == null) ? (int?)null : a.Value + b.Value
    }
    

    我认为如果您试图将结果赋给一个不可为空的值,编译器将被迫使用不可为空的重载,并将x转换为int。

    e.g. int i = x + 1;  //throws runtime exception
    
        5
  •  0
  •   Paul    15 年前

    不幸的是,没有。 X 在x= X +1和第一行一样为空,所以您要将1添加到空,等于空。

    因为它是一个可以为空的int,所以可以使用x.hasValue检查它是否有值,然后使用x.Value获取实际的int值。

        6
  •  0
  •   Wim    15 年前

    不管是否 x 实际上永远不会是空的,这甚至不是重点。

    关键是,你什么时候见过 NullReferenceException 尝试执行添加操作时?

    下面的示例不抛出 空引用异常 两者都是完全有效的。

    string hello = null;
    string world = "world";
    string hw = hello+world;
    

    你只会得到一个 空引用异常 如果试图访问空对象上的成员。

        7
  •  -1
  •   Community Nick Dandoulakis    7 年前

    int?不能为空,因为它是一个结构。结构位于堆栈上,堆栈不能很好地处理空值。

    What is a NullPointerException, and how do I fix it?

    此外,可以为空的类型有两个非常有用的属性:hasValue、value

    此代码:

            if (x != null)
            {
                return (int) x;
            }
    

    应重构为:

            if (x.HasValue)
            {
                return x.Value;
            }