【问题标题】:Why is there no exception when adding null to a string?为什么将null添加到字符串时没有异常?
【发布时间】:2011-03-19 18:09:38
【问题描述】:

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

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

【问题讨论】:

  • 对于空引用,可能有一个默认的字符串实现。控制台输出是什么?
  • 为了将来参考,如果您使用有意义的问题标题,您可能会得到更好的响应。当然你会得到答案,但总的来说,人们更喜欢看能说明他们是什么的问题......

标签: c# string-concatenation


【解决方案1】:

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

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

所以...

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

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

一定会抛出异常

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

对于有问题的代码,您传递给Console.WriteLine 的参数实际上是对string.Concat 的编译调用的结果,它允许null 值作为参数传递并基本上忽略它们 - - 作为SLaks already pointed out


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

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

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

【讨论】:

  • 并非总是如此。 Int? obj = null; obj.GetHashCode() 返回0
  • @SLaks:嗯,你可以这么说。但你我都知道int? obj = null; 中的null 并不是真正的null
  • @Dan Bryant:是的,是的,但扩展方法不算作会员访问!啊,我需要修正这个答案,看来;)
  • @Dan Tao,软件工程师一直在寻找极端案例:)
  • @Dan Bryant:看看我的答案现在看起来多么残酷,加上所有那些可怕的脚注。该死的你和你的吹毛求疵!
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      如果您在实际应用程序中遇到问题,您始终可以在显示文本之前检查 null。然后,您可以显示替代文本,或者什么都不显示。

      【讨论】:

      【解决方案5】:

      编译成

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

      String.Concat method 忽略 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; 
          }
      

      【讨论】:

      • 如果arg0==null,它不会返回arg1.ToString(),因为arg1也可能为null,这会导致异常。双重检查是在 ConCat 的字符串版本中处理的,所以我们失去的只是一个方法调用。
      • @James:它可以立即进行额外的null 检查和return String.Empty。我们也失去了额外的String.Empty 电话。 (尽管它们可能被 JITter 内联)
      猜你喜欢
      • 1970-01-01
      • 2020-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多