在我可以安全地应用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.
其他回答
为什么字符串类型的默认值为空而不是空 字符串?
因为string是一个引用类型,所有引用类型的默认值都是null。
在我可以之前,测试我所有的字符串是否为null是非常烦人的 安全应用方法,如ToUpper(), StartWith()等…
这与引用类型的行为一致。在调用它们的实例成员之前,应该对空引用进行检查。
如果string的默认值是空字符串,我就不会有 来测试,我觉得它和另一个更一致 例如int或double这样的值类型。
将默认值分配给一个特定的引用类型而不是null会使它不一致。
此外,Nullable<String>也有意义。
Nullable<T>适用于值类型。值得注意的是,Nullable并没有在最初的。net平台上引入,所以如果他们改变了这一规则,就会有很多坏代码。(礼貌@jcolebrand)
既然你提到了ToUpper(),这种用法是我如何找到这个线程的,我将分享这个快捷方式(字符串??" ") .ToUpper ():
private string _city;
public string City
{
get
{
return (this._city ?? "").ToUpper();
}
set
{
this._city = value;
}
}
似乎比:
if(null != this._city)
{ this._city = this._city.ToUpper(); }
从c# 6.0开始,您还可以使用以下代码
string myString = null;
string result = myString?.ToUpper();
字符串结果将为空。
空字符串和空字符串是完全不同的。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
因为字符串变量是引用,而不是实例。
在默认情况下将其初始化为Empty是可能的,但这将在整个板上引入许多不一致。