为什么这段代码是有效的 C# 代码



可能的重复项:
C#:为什么在字符串中添加 null 是合法的?

下面是有效的 C# 代码:

var samsung= "xyz" + null + null + null + null + "890";  // xyz890

这是无效的 C# 代码:

var iphone= null.ToString(); // compiler error

为什么以及如何第一个语句有效而第二个语句无效?

+运算符用于连接字符串,由于null是字符串类的实例,因此可以用作运算符的参数。 "xyz" + null最终返回字符串"xyz",因此只是重复此过程,直到您实际添加"890"

虽然 null 可以用作方法参数的字符串对象,但实际上不能对其调用方法,因为没有内容可以处理方法调用。

将方法视为对象处理外部请求的一种方式,事情更有意义。您可以使用null向对象发送请求作为要处理的内容的参数,但实际上不能要求null处理某些内容。

使用第一行,您正在连接字符串。 null什么都不是,所以基本上你得到了xyz890. 这就像做1+0+0+0+4但是对于你的第二个,你被称为ToString() null. null什么都不是,所以没有什么可以叫ToString()的。 您正在尝试对未初始化的变量调用方法。

由于 string 是引用类型,因此 null 可以隐式转换为 string 。在第一种情况下,+运算符序列只是转换为String.Concat(obj1, obj2, obj3, ...)

要使代码编译,您可以调用Convert.ToString

var iphone = Convert.ToString(null);
您可以将

+ 运算符视为全局静态函数,如下所示:

+(string leftHandSide, string rightHandSide) {
  if (leftHandSide == null)
     leftHandSide = string.Empty;
  if (rightHandSide == null)
     rightHandSide = string.Empty;
  string returnValue;
  // concatenate string
  return returnValue;
}

由于此字符串串联方法是静态的,因此不需要实例来调用它,它处理空值。但是,当您尝试在null上调用ToString时,没有对象的实例,因此没有要调用ToString mehthod,因此异常。

C# 编译器将串联中的 null 视为空字符串。

 var samsung= "xyz" + null + null + null + null + "890";

等于

 var samsung= "xyz" + ""+ ""+ ""+ ""+ "890";

当您尝试调用null.toString()时,您实际上是在尝试在 null 对象上调用方法,该方法(如果编译)总是会导致NullReferenceException

这是设计使然。您可以阅读 C# 语言规范。报价:

字符串连接:

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

二进制+运算符的这些重载执行字符串串联。 如果null字符串连接的操作数,则空字符串为 取代。否则,任何非字符串参数都将转换为其 通过调用虚拟ToString方法表示字符串 继承自 object 型 。如果ToString返回 null ,则为空字符串 被替换。

[...]

因此,正如其他人所说,将+视为一种接受两个参数的方法,并且可以null其中一个或两个参数。

+ 运算符将被转换为一个静态函数,如下所示:

public static string Concat(string first, string second) {...}

将 null 作为参数传递给函数不是问题;它传递得很好。 该函数碰巧在连接它们之前检查两个参数都不是 null;如果任何参数为 null,则将它们视为空字符串,以免导致异常。 这里的关键点是,在此函数首次检查字符串 null 之前,不会调用字符串的实例成员。

至于null.ToString()在编译时计算结果为 null 的任何内容上调用实例函数会导致异常。 这就是该案的定义。

因为在任何情况下都不能在null引用上调用方法,所以编译器不允许这样做。 在第一种情况下,编译器会将字符串常量预编译为"xyz890"因此它是合法赋值。

通常,string+运算符编译为支持null参数的String.Concat(s1, s2, ...)

更准确地说,第二种情况,实际问题不在于它是一个空指针,而在于没有将方法绑定到的类型。 正如其他注释中指出的,您可以将null转换为任何引用类型,并且可以很好地编译:

((string)null).ToString();   // compiles, but fails at run-time.

如果您查看 IL,您会发现编译器足够聪明,只需删除 null 值并创建一个串联字符串。 如前所述,您不能执行空值。ToString();你可以做字符串。为空或将字符串分配为 null。

.method private hidebysig static void  Main() cil managed
{
  .entrypoint
  // Code size       8 (0x8)
  .maxstack  1
  .locals init ([0] string samsung)
  IL_0000:  nop
  IL_0001:  ldstr      "xyz890"        //null has been removed by compiler.  
  IL_0006:  stloc.0
  IL_0007:  ret
} // end of method Program::Main 

编辑
扩展尼尔森的评论。 由于 null 表示 nil 引用,因此可以公平地说,处理字符串 concat 的方式是 C# 允许,例如操作。 我会理解它使用字节数组构建,它会省略空值,从而简单地让它看起来像是连接空值。

相关内容

  • 没有找到相关文章

最新更新