17

我只是想知道下两个语句之间有什么区别:

  1. 导致 NullReferenceException - 没关系。

    object test1 = default(int?);
    object result = test1.ToString();
    
  2. 返回一个空字符串“”,为什么?

    object test2 = default(int?).ToString();
    
  3. 这与 2 相同。

    int? test3 = null;
    if (test3.ToString() == string.Empty) //returns true
    {
        Console.WriteLine("int? = String.Empty, isn't it strange?").
    }
    
  4. 只是为了好玩-我可以证明 bool 可以等于 int 值(嗯,怎么样? bool 只能是假的,或者真和 int 永远不可能)。

    if (default(int?).ToString() == default(bool?).ToString()) //returns true because both are empty strings
    {
        Console.WriteLine("int = bool");
    }
    

注意: default(int?) 返回 null。

4

2 回答 2

31

一个int?是一个Nullable<int>Nullable是一个struct,这使它成为一个值类型,而不是一个引用类型。 test3实际上并未设置为null. 分配null给它实际上会导致创建一个新结构,该结构只是将该HasValue结构的字段设置为false而不是true. (发生这种隐式转换需要特殊的编译器支持;因此您不能拥有自己的MyNullable<T>类型来执行此操作。)

由于可空对象有一个实际值,它可以调用ToString并提供一个有意义的值,在这种情况下是一个空字符串。

当您通过将可空值放入object变量中来装箱该可空值时,它将导致实际 null值存储在该变量中,这就是为什么在对其调用方法时会得到 NRE 的原因。

当可空值类型被装箱时,它不会装箱可空值类型;相反,如果它没有分配null给对象的值,如果它有一个值,则该底层值被解包然后装箱。(此行为需要运行时的特殊支持,这是您无法创建自己的类型的另一个原因MyNullable<T>。)

于 2013-10-18T17:25:54.207 回答
1

在 C 中,使用令牌.访问左操作数的成员,并->访问左操作数持有指针(引用)的事物的成员。如果 的左侧操作数->为空,则发生空引用。在 C# 中,.应用于值类型时具有前者的含义,而应用于类类型时具有后者的含义;.在 C# 中对 null 的类类型变量使用将触发NullReferenceException.

.NET 类型Nullable<T>是一个双字段结构,其中包含指示它是否具有有意义(非空)值的布尔字段和表示T该值是什么(如果不为空)的值类型字段。尽管编译器允许将 a 分配Nullable<T>给 null 或将 a 与 null 进行比较,null但在前一种情况下,实际上只是默认实例的简写(其中“has-value”标志为假,并且 value 字段保存默认值对于类型 T),与 null 的比较实际上只是检查HasValue属性的简写(它反过来查看Boolean字段)。调用ToString例如为“null”的 a 在语义上与在包含 a和 an 的Nullable<int>任何其他结构上调用它没有什么不同BooleanInt32分别具有值False0。编译器有几种“特殊”处理可空类型的方法,但默认值Nullable<int>保持[False, 0],而不是空引用。

请注意,第一个示例由于框架应用于可空类型的“特殊”规则之一而引发。将值类型转换为Object或另一个引用类型通常会指示运行时创建一个对象,该对象将作为一个类对象,其字段和成员与结构的字段和成员匹配,并返回对该新对象的引用——一个称为“装箱”的过程. 因为可空类型的设计者希望允许代码说if (NullableThing == null)而不是(恕我直言,语义上更清晰)if (!NullableThing.HasValue),所以实现了运行时,以便将HasValue字段为 false 的可空对象装箱将产生空引用,而不是对默认值实例的引用Nullable<T>. 虽然我认为在某些情况下让某些值类型使用不同的装箱和拆箱方法是有意义的,但可空类型是唯一可以使用除普通装箱之外的任何东西的类型。

于 2013-10-18T19:51:29.213 回答