在我可以安全地应用ToUpper(), StartWith()等方法之前,测试我所有的字符串为空是非常烦人的…
如果字符串的默认值是空字符串,我就不必测试,而且我觉得它与其他值类型(例如int或double)更一致。 此外,Nullable<String>也有意义。
那么为什么c#的设计者选择使用null作为字符串的默认值呢?
注意:这与这个问题有关,但更关注的是为什么,而不是如何处理它。
在我可以安全地应用ToUpper(), StartWith()等方法之前,测试我所有的字符串为空是非常烦人的…
如果字符串的默认值是空字符串,我就不必测试,而且我觉得它与其他值类型(例如int或double)更一致。 此外,Nullable<String>也有意义。
那么为什么c#的设计者选择使用null作为字符串的默认值呢?
注意:这与这个问题有关,但更关注的是为什么,而不是如何处理它。
当前回答
最根本的原因/问题是CLS规范(定义了语言如何与。net交互)的设计者没有定义一种方法,通过这种方法,类成员可以指定它们必须直接被调用,而不是通过callvirt,而调用方不执行空引用检查;它也没有提供一种定义不受“正常”装箱约束的结构的方法。
Had the CLS specification defined such a means, then it would be possible for .net to consistently follow the lead established by the Common Object Model (COM), under which a null string reference was considered semantically equivalent to an empty string, and for other user-defined immutable class types which are supposed to have value semantics to likewise define default values. Essentially, what would happen would be for each member of String, e.g. Length to be written as something like [InvokableOnNull()] int String Length { get { if (this==null) return 0; else return _Length;} }. This approach would have offered very nice semantics for things which should behave like values, but because of implementation issues need to be stored on the heap. The biggest difficulty with this approach is that the semantics of conversion between such types and Object could get a little murky.
An alternative approach would have been to allow the definition of special structure types which did not inherit from Object but instead had custom boxing and unboxing operations (which would convert to/from some other class type). Under such an approach, there would be a class type NullableString which behaves as string does now, and a custom-boxed struct type String, which would hold a single private field Value of type String. Attempting to convert a String to NullableString or Object would return Value if non-null, or String.Empty if null. Attempting to cast to String, a non-null reference to a NullableString instance would store the reference in Value (perhaps storing null if the length was zero); casting any other reference would throw an exception.
Even though strings have to be stored on the heap, there is conceptually no reason why they shouldn't behave like value types that have a non-null default value. Having them be stored as a "normal" structure which held a reference would have been efficient for code that used them as type "string", but would have added an extra layer of indirection and inefficiency when casting to "object". While I don't foresee .net adding either of the above features at this late date, perhaps designers of future frameworks might consider including them.
其他回答
空字符串和空字符串是完全不同的。null是指没有值,空字符串是指空值。
编程语言对变量的“值”(在这种情况下是空字符串)进行假设,与使用任何其他不会导致空引用问题的值初始化字符串一样好。
同样,如果您将该字符串变量的句柄传递给应用程序的其他部分,那么该代码将无法验证您是故意传递了一个空白值,还是忘记填充该变量的值。
Another occasion where this would be a problem is when the string is a return value from some function. Since string is a reference type and can technically have a value as null and empty both, therefore the function can also technically return a null or empty (there is nothing to stop it from doing so). Now, since there are 2 notions of the "absence of a value", i.e an empty string and a null, all the code that consumes this function will have to do 2 checks. One for empty and the other for null.
简而言之,一个状态只有一种表示总是好的。有关empty和nulls的更广泛讨论,请参阅下面的链接。
https://softwareengineering.stackexchange.com/questions/32578/sql-empty-string-vs-null-value
在处理用户输入时,NULL vs Empty
如果string的默认值是空字符串,我就不必进行测试
错了!更改默认值并不会改变它是引用类型的事实,并且有人仍然可以显式地将引用设置为空。
此外,Nullable<String>也有意义。
真正的点。不允许任何引用类型为空会更有意义,而需要Nullable<TheRefType>作为该特性。
那么为什么c#的设计者选择使用null作为字符串的默认值呢?
与其他引用类型的一致性。现在,为什么在引用类型中允许空呢?可能会让它感觉像C语言,尽管在一种也提供Nullable的语言中,这是一个有问题的设计决策。
String是一个不可变对象,这意味着当给定一个值时,旧的值不会从内存中删除,而是保留在旧的位置,而新值则放在新的位置。如果String a的默认值是String。空,它将浪费字符串。当它被赋予第一个值时,内存中的空块。
虽然它看起来微不足道,但在初始化一个默认值为String.Empty的大型字符串数组时,它可能会变成一个问题。当然,如果这将成为一个问题,您总是可以使用可变的StringBuilder类。
Habib是对的——因为字符串是引用类型。
但更重要的是,您不必每次使用它时都检查是否为null。如果有人给你的函数传递一个空引用,你可能应该抛出一个ArgumentNullException。
事情是这样的——无论如何,如果你试图对字符串调用. toupper(),框架都会为你抛出一个NullReferenceException。记住,即使你测试你的参数为空,这种情况仍然会发生,因为传递给你的函数作为参数的对象上的任何属性或方法都可能求值为空。
也就是说,检查空字符串或null是一件常见的事情,因此他们提供String.IsNullOrEmpty()和string . isnullowhitespace()仅用于此目的。
也许你可以用??运算符赋值字符串变量时,它可能会有帮助。
string str = SomeMethodThatReturnsaString() ?? "";
// if SomeMethodThatReturnsaString() returns a null value, "" is assigned to str.