10

为什么不抛出异常不明白,obj 为 null

object obj = null;
Console.WriteLine("Hello World " + obj);
4

5 回答 5

21

这编译为

Console.WriteLine(String.Concat("Hello World ", obj));

String.Concat方法忽略null参数。

它是这样定义的:(来自.Net参考源)

    public static String Concat(Object arg0, Object arg1) {
        if (arg0==null) {
            arg0 = String.Empty; 
        }

        if (arg1==null) { 
            arg1 = String.Empty;
        } 
        return Concat(arg0.ToString(), arg1.ToString());
    }

我不知道为什么它不简单地返回arg1.ToString()if arg0==null

String.Concat(string, string)方法定义如下:

    public static String Concat(String str0, String str1) { 
        if (IsNullOrEmpty(str0)) { 
            if (IsNullOrEmpty(str1)) {
                return String.Empty; 
            }
            return str1;
        }

        if (IsNullOrEmpty(str1)) {
            return str0; 
        } 

        int str0Length = str0.Length; 

        String result = FastAllocateString(str0Length + str1.Length);

        FillStringChecked(result, 0,        str0); 
        FillStringChecked(result, str0Length, str1);

        return result; 
    }
于 2010-07-22T19:16:36.997 回答
3

将参数传递null给方法不一定会引发异常;这取决于方法的实现(在这种情况下,您可能会看到一个ArgumentNullException)。

尝试访问对象**的成员*总是会抛出, 保证***。nullNullReferenceException

所以...

可能会或可能不会抛出异常

object obj = null;
SomeMethod(obj); // passing as parameter

肯定会抛出异常

object obj = null;
int hashCode = obj.GetHashCode(); // calling instance method

对于有问题的代码,您传递给的参数Console.WriteLine实际上是编译调用的结果string.Concat,它允许null将值作为参数传递并基本上忽略它们——正如SLaks 已经指出的那样


*扩展方法是另一回事;它们可以在“空”参数上调用;但由于这些只是呈现出类似于实例方法的错觉,因此该规则不适用于它们。事实上,扩展方法毕竟只是静态方法。如果你调用一个“on”一个null值,你实际上是null作为一个参数传递的。

**这里我不包括Nullable<T>带有HasValue == false;的值 尽管在许多情况下这些可能被方便地对待null,但这只是为了语法上的方便:它们只不过是null任何其他值类型都可以null

***我在这里谈论 C#。正如 SLaks 在评论中指出的那样,这不是 CLI 本身的规则。但是 C# 中的所有实例方法调用都编译为callvirtIL 中的指令,如果实例是null.

于 2010-07-22T19:20:28.583 回答
1

因为那会很烦人。对于大多数目的来说,空字符串和空字符串之间没有语义差异。

于 2010-07-22T19:21:01.563 回答
0

因为他们实现了 String.IsNullOrEmpty 并将其留给我们来弄清楚如何使用它。

于 2010-07-22T19:24:50.460 回答
0

如果您有可能在实际应用程序中发生这种情况的问题,您可以在显示文本之前始终检查 null。然后,您可以显示替代文本,或者什么都不显示。

于 2010-07-22T19:19:42.763 回答