为什么null语句ToString()返回一个空字符串?

时间:2013-10-18 17:21:37

标签: c# nullable

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

  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只能是false,或者是true而int永远不会那样)。

    if (default(int?).ToString() == default(bool?).ToString()) //returns true because both are empty strings
    {
        Console.WriteLine("int = bool");
    }
    
  5. 注意: default(int?)返回null。

2 个答案:

答案 0 :(得分:29)

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

由于可空对象具有实际值,因此它可以调用ToString并提供有意义的值,在本例中为空字符串。

当您将该可空值放入object变量中时,它会导致实际 null值存储在该变量中,这就是您获得的原因在调用方法时使用NRE。

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

答案 1 :(得分:1)

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

.NET类型Nullable<T>是一个双字段结构,它包含指示它是否具有有意义(非空)值的布尔字段,以及值类型T的字段来说明这是什么value是(如果不为null)。虽然编译器允许将Nullable<T>指定为null或将其与null进行比较,但前一种情况下的null实际上只是默认实例的简写(其中“has-value”标志为false,并且value字段保存类型T的默认值,并且与null的比较实际上只是检查HasValue属性(它依次查看Boolean字段)的简写。在{例如}上调用ToString Nullable<int>“null”在语义上与在包含BooleanInt32且值False和{{1}的任何其他结构上调用它没有区别}}, 分别。编译器有几种方法可以“特殊”处理可空类型,但默认值0包含Nullable<int>,而不是空引用。

请注意,第一个示例因为框架应用于可空类型的“特殊”规则之一而抛出。将值类型转换为[False, 0]或其他引用类型通常会指示运行时创建一个对象,该对象将作为类对象运行,其中字段和成员与结构的对象匹配,并返回对该新对象的引用 - 一个进程被称为“拳击”。因为可空类型的设计者希望允许代码说Object而不是(IMHO更清晰)if (NullableThing == null),所以实现了运行时,以便装入if (!NullableThing.HasValue)字段为false的可空字段产生空引用而不是对HasValue的默认值实例的引用。虽然我认为有些情况下某些值类型使用不同的box和unbox方法是有意义的,但可空类型是唯一可以使用除正常装箱之外的其他类型。