C#添加字符串+ null不会抛出错误?

作为一名程序员,我本以为这会抛出exception。 是否有理由将null视为“”?

string s = "hello"; string t = null; Console.WriteLine(s + t); 

输出:

你好

只是为了强调我的问题,你知道为什么决定将null变为String.Empty吗? 我期待一些字符串被添加,但是有一个问题进一步回到它没有正确检索它并返回null。 问题没有被注意到!

这是一个伪代码,为什么我认为它是坏的(为什么我发现没有错误感到震惊):

您可以假设我重载了ToString以提供该人员的姓名或有关他们的详细信息。

 Person p = PersonDatabase.GetForName("Jimmy Gibbs"); Console.WriteLine("Name is: " + p.ToString()); 

引发exception,因为p为null

 String p = PersonDatabase.GetForName("Jimmy Gibbs").Name; Console.WriteLine("Name is: " + p); 

即使p为null(它将其视为“”),也不会抛出exception。

(如果你想挑剔并说我将无法获得Name,因为GetforName将为null,请将其视为此:)

 String p = PersonDatabase.GetNameFromID(1234); // Returns a string or null if not found Console.WriteLine("Name is: " + p); 

(如果你在列表或数组中使用这个值,你最终会得到一个空白的条目,这对我来说是破坏的,它创建了javascript并试图获得ID为“”的元素)

来自C#语言规范 :

7.8.4加法运算符

字符串连接:

string operator +(string x,string y); string operator +(string x,object y); string operator +(object x,string y);

二进制+运算符的这些重载执行字符串连接。 如果字符串连接的操作数为null,则替换空字符串。 否则,通过调用从类型对象inheritance的虚拟ToString方法,将任何非字符串参数转换为其字符串表示forms。 如果ToString返回null,则替换空字符串。

+运算符在生成的IL中作为string.Concat发出。

 s + t = string.Concat(s, t) 

在查看实现时,它会检查参数是否为null并返回string.Empty:

用reflection器拆卸:

 [SecuritySafeCritical] public static string Concat(string str0, string str1) { if (IsNullOrEmpty(str0)) { if (IsNullOrEmpty(str1)) { return Empty; } return str1; } if (IsNullOrEmpty(str1)) { return str0; } int length = str0.Length; string dest = FastAllocateString(length + str1.Length); FillStringChecked(dest, 0, str0); FillStringChecked(dest, length, str1); return dest; } 

在字符串连接操作中,C#编译器将空字符串视为空字符串,但它不会转换原始空字符串的值。 其他信息,请访问http://msdn.microsoft.com/en-us/library/aa691375(VS.71).aspx

如果我有一个橙色并添加另一个橙色,我现在有两个橙子。

如果我有一个橙色并添加NOTHING,我仍然有橙色。

我向字符串添加NULL并获取原始字符串似乎非常直观和语义。 在访问不存在的实例上的Properties或实例方法时,应保留NullReferenceExceptions,例如。

 string myString = null; string lowerCaseString = myString.ToLower(); 

可以理解地抛出一个NullReferenceException,因为我试图访问不存在的引用上的ToLower()实例方法,因此Null 引用exception(即堆栈上有一个东西,但堆上没有任何东西)。

使用NULL字符串concat操作抛出exception意味着在处理字符串时会有大量额外的防御性NULL代码检查,这很烦人。 抱歉,我碰巧同意C#.NET如何处理这个问题。 Java不一样吗?


如果要检查字符串是否包含值,请使用String.IsNullOrEmpty(myString);String.IsNullOrWhitespace(myString); (仅在.NET 4.0中)

在考虑所做的设计决策时,我们不仅应该查看字符串的plus运算符,还要查看相关的类和方法,例如String.Concat(String,String)和StringBuilder.Append(String) 。 这些类是Base Class Library的一部分,它广泛用于其他语言(例如Visual Basic和F#)。

从语言和平台设计的角度来看,所有这些方法都应该在一致的派系中运行(即以相同的方式处理null)。 我看到三种可能的选择:

  • 抛出exception

    这是一个“安全”的解决方案,因为它不清楚如何处理null。 作为权衡,它需要更具防御性的编程风格和更冗长的代码。

  • 使用一些表示为null,例如null[null] (Java样式)

    这是您期望的结果。 目前尚不清楚为什么会发生这种情况以及应该如何表示零。

  • 以与空字符串相同的方式处理null(.NET样式)

    它背后的想法是null的文本表示(即缺少的对象)是一个空字符串。 在这种情况下,程序员可以利用此行为并编写更短的代码。 另一方面,它可以隐藏错误。

必须作出一些决定,我认为没有明显的选择。 C#和其他.NET语言中的预期行为已明确记录,并且在处理串联的所有方法中都是一致的。

用户定义的运算符只是静态方法,当然可以接受null参数。 例如,这对代表来说非常有用。

因此,接受null字符串不是技术性的,而是设计决策。 并且将null视为“”有时可能是有用的,因为很多用户代码都将它们视为相同。

实际上这是字符串的表示方式….没有错。 null用作终止字符。

例如:

字符串a:“blahblah [null]”所以无论什么读取字符串都知道停止在null。

所以当你创建一个这样的字符串时:string b:“[null]”它完全有效。

现在,null之前没有字符。 所以,当你的程序开始读取字符串时,它遇到null(完全有效)并停止….因此……空字符串!!