为什么字符串的默认值为null而不是空字符串?

问题描述 投票:202回答:14

在我可以安全地应用像qazxsw poi,qazxsw poi等方法之前,测试qazxsw poi的所有字符串是非常烦人的...

如果null的默认值是空字符串,我就不必测试,我觉得它与ToUpper()StartWith()等其他值类型更加一致。另外string会有意义。

那么为什么C#的设计者选择使用int作为字符串的默认值?

注意:这与double有关,但更侧重于为什么而不是如何处理它。

c# string default-value
14个回答
297
投票

为什么字符串的默认值为null而不是空字符串?

因为Nullable<String>是引用类型,所有引用类型的默认值是null

在我可以安全地应用ToUpper(),StartWith()等方法之前,测试我的所有字符串是非常烦人的...

这与引用类型的行为一致。在调用实例成员之前,应该对空引用进行检查。

如果string的默认值是空字符串,我就不必测试了,我觉得它与其他值类型(例如int或double)更加一致。

将默认值分配给this question以外的特定引用类型会使其不一致。

另外string会有意义。

null使用值类型。值得注意的是,null没有在原来的Nullable<String>上引入,所以如果他们改变了这条规则就会有很多破碎的代码。(礼貌Nullable<T>


3
投票

也许如果您在分配字符串变量时使用null运算符,它可能会对您有所帮助。

null

2
投票

String是一个不可变对象,这意味着当给定值时,旧值不会从内存中消失,而是保留在旧位置,并将新值放在新位置。因此,如果Nullable的默认值是??,那么当它被赋予第一个值时,它会浪费string str = SomeMethodThatReturnsaString() ?? ""; // if SomeMethodThatReturnsaString() returns a null value, "" is assigned to str. 块在内存中。

尽管看起来微不足道,但在使用默认值String a初始化大量字符串时,它可能会变成一个问题。当然,如果这是一个问题,你总是可以使用可变的String.Empty类。


2
投票

由于string是引用类型,因此引用类型的默认值为null。


0
投票

也许String.Empty关键字让你困惑,因为它看起来与任何其他值类型声明完全一样,但它实际上是String.Empty中的StringBuilder的别名。 此外,Visual Studio中的深蓝色和小写的第一个字母可能误导为认为它是string


0
投票

Nullable类型直到2.0才出现。

如果在语言的开头有可空类型,那么字符串将是不可为空的字符串?本来可以为空的。但他们无法做到向后兼容。

很多人都在谈论ref-type或者不是ref类型,但是string是一个与众不同的类,并且已经发现解决方案可以实现。


40
投票

哈比卜是对的 - 因为Nullable是参考类型。

但更重要的是,每次使用时都不必检查.NET platform。如果有人通过你的函数@jcolebrand引用,你可能应该抛出string

这就是事情 - 如果你试图在一个字符串上调用null,框架会为你抛出一个ArgumentNullException。请记住,即使您测试null的参数,这种情况仍然会发生,因为作为参数传递给函数的对象上的任何属性或方法都可以计算为NullReferenceException

话虽这么说,检查空字符串或空值是常见的事情,所以他们提供.ToUpper()null就是为了这个目的。


23
投票

你可以写一个null(为了它的价值):

String.IsNullOrEmpty()

现在这安全地工作:

String.IsNullOrWhiteSpace()

15
投票

您也可以(从VS2015和新编译器开始)使用以下内容

extension method

字符串结果将为null。


14
投票

空字符串和空值根本不同。 null表示缺少值,空字符串表示空值。

编程语言对变量的“值”进行假设,在本例中为空字符串,与使用任何其他不会导致空引用问题的值初始化字符串一样好。

此外,如果将句柄传递给该字符串变量到应用程序的其他部分,那么该代码将无法验证您是否故意传递了空白值,或者您忘记填充该变量的值。

另一个会出现问题的场合是字符串是某个函数的返回值。由于string是一个引用类型,并且在技术上可以将值设置为null并且两者都为空,因此该函数在技术上也可以返回null或空(没有什么可以阻止它这样做)。现在,由于存在2个“缺少值”的概念,即空字符串和空值,所有使用此函数的代码都必须进行2次检查。一个用于空,另一个用于null。

简而言之,对于单个状态只有1个表示总是好的。有关empty和nulls的更广泛讨论,请参阅下面的链接。

public static string EmptyNull(this string str) { return str ?? ""; }

string str = null; string upper = str.EmptyNull().ToUpper();


7
投票

根本原因/问题是CLS规范的设计者(定义语言如何与.net交互)没有定义一种方法,通过该方法,类成员可以指定必须直接调用它们,而不是通过string myString = null; string result = myString?.ToUpper(); ,而不需要调用者执行空引用检查;它也没有提供任何不受“正常”拳击影响的定义结构。

如果CLS规范定义了这样一种方法,那么.net就有可能始终遵循公共对象模型(COM)建立的线索,在该线索下,空字符串引用被认为在语义上等同于空字符串,而对于其他用户定义的不可变类类型,它们应具有值语义,以同样定义默认值。基本上,对于https://softwareengineering.stackexchange.com/questions/32578/sql-empty-string-vs-null-value的每个成员,会发生什么,例如NULL vs Empty when dealing with user input写成像callvirt。这种方法可以为应该表现得像值的事物提供非常好的语义,但是由于实现问题需要存储在堆上。这种方法最大的困难在于这些类型和String之间转换的语义可能会有点模糊。

另一种方法是允许定义特殊结构类型,这些类型不是从Length继承而是具有自定义装箱和拆箱操作(可以转换为/从某些其他类类型转换)。在这种方法下,会有一个类型为[InvokableOnNull()] int String Length { get { if (this==null) return 0; else return _Length;} },其行为与现在的字符串一样,以及一个自定义框结构类型Object,它将包含Object类型的单个私有字段NullableString。尝试将String转换为ValueString如果非null则返回String,如果为null则返回NullableString。试图转换为Object,对Value实例的非空引用会将引用存储在String.Empty中(如果长度为零,则可能存储null);转换任何其他引用将引发异常。

即使字符串必须存储在堆上,概念上也没有理由说它们不应该像具有非空默认值的值类型一样。将它们存储为保持引用的“普通”结构对于将它们用作类型“字符串”的代码是有效的,但是在转换为“对象”时会增加额外的间接层和低效率。虽然我没有预见.net会在这个晚期添加上述任何一个功能,但未来框架的设计者可能会考虑将它们包括在内。


5
投票

因为字符串变量是引用,而不是实例。

默认情况下将其初始化为Empty是可能的,但它会在整个板上引入很多不一致的地方。


5
投票

为什么C#的设计者选择使用null作为字符串的默认值?

因为字符串是引用类型,所以引用类型的默认值是String。引用类型的变量存储对实际数据的引用。

我们在这种情况下使用NullableString关键字;

Value

null是一个default,所以它是一个引用类型,所以默认值是string str = default(string);

str

string是一个null,所以它是一个值类型,所以默认值是int str = (default)(int);


4
投票

如果str的默认值是空字符串,我就不必测试了

错误!更改默认值不会改变它是引用类型的事实,并且有人仍然可以将引用显式设置为int

另外zero会有意义。

真实的一点。不允许string用于任何参考类型更有意义,而是需要null用于该功能。

那么为什么C#的设计者选择使用Nullable<String>作为字符串的默认值?

与其他参考类型的一致性。现在,为什么允许null参考类型呢?可能让它感觉像是C,尽管这是一个有问题的设计决定,在一种语言中也提供Nullable<TheRefType>

© www.soinside.com 2019 - 2024. All rights reserved.