为什么stringtypes的默认值是null而不是空string?

在我可以安全地应用ToUpper()StartWith()等方法之前,testing我的所有string为null是非常烦人的。

如果string的默认值是空string,我不需要testing,我会觉得它是更一致的其他值types,如intdouble例如。 此外, Nullable<String>将是有意义的。

那么为什么C#的devise者select使用null作为string的默认值呢?

注意:这涉及到这个问题 ,但更关注为什么而不是如何处理它。

为什么stringtypes的默认值是null而不是空string?

因为string引用types ,所有引用types的默认值为null

在我可以安全地应用ToUpper(),StartWith()等方法之前,testing我的所有string为null是非常烦人的。

这与参考types的行为一致。 在调用它们的实例成员之前,应该先检查一个空引用。

如果string的默认值是空string,我不需要testing,我会觉得它是更一致的其他值types,如int或double例如。

将默认值分配给非null的特定引用types会使其不一致

此外, Nullable<String>将是有意义的。

Nullable<T>与值types一起使用。 值得注意的是Nullable并没有在原来的.NET平台上引入,所以如果他们改变了这个规则,就会出现很多破坏的代码( Courtesy @jcolebrand )

Habib是正确的 – 因为string是一个引用types。

但更重要的是,每次使用时都不必检查null 。 不过,如果有人将你的函数传递给null引用,你可能应该抛出一个ArgumentNullException

这是事情 – 如果您尝试在string上调用.ToUpper() ,框架将为您抛出NullReferenceException 。 记住即使你testing你的参数为null也会发生这种情况,因为作为parameter passing给你的函数的对象上的任何属性或方法可能评估为null

这就是说,检查空string或空值是一个常见的事情,所以他们提供String.IsNullOrEmpty()String.IsNullOrWhiteSpace()正是为了这个目的。

你可以写一个扩展方法 (值得):

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

现在这个工作安全:

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

空string和空值是根本不同的。 null是缺less值,空string是空的值。

编程语言对variables的“值”(在这种情况下为空string)做出假设,就像使用任何其他不会导致空引用问题的值来初始化string一样好。

另外,如果将句柄传递给应用程序的其他部分,则该代码将无法validation是否有意传递了空值,或者忘记填充该variables的值。

另外一个问题是当string是某个函数的返回值时。 由于string是一个引用types,并且在技术上可以有一个值为null和empty,因此该函数也可以在技术上返回null或empty(这样做没有任何阻止)。 现在,由于有2个“缺less值”的概念,即一个空string和一个空值,所有使用这个函数的代码将不得不做2次检查。 一个是空的,另一个是空的。

总之,它总是有一个单一的状态只有一个代表。 有关空白和空值的更广泛讨论,请参阅下面的链接。

https://softwareengineering.stackexchange.com/questions/32578/sql-empty-string-vs-null-value

处理用户input时为空vs空

我知道我对这里的派对有点晚了,但是如果有人碰到这个,你也可以(从VS2015和新的编译器开始)使用以下

 string myString = null; string result = myString?.ToUpper(); 

string结果将为空。

因为一个stringvariables是一个引用 ,而不是一个实例

默认情况下将其初始化为空将是可能的,但是会引起很多不一致的情况。

为什么C#的devise者select使用null作为string的默认值?

由于string是引用types ,引用types是默认值为null 。 引用types的variables存储对实际数据的引用。

我们在这个案例中使用default关键字;

 string str = default(string); 

str是一个string ,所以它是一个引用types ,所以默认值是null

 int str = (default)(int); 

str是一个int ,所以它是一个值types ,所以默认值是zero

根本原因/问题是CLS规范(定义语言如何与.net交互)的devise者没有定义类成员可以指定它们必须直接调用的方式,而不是通过callvirt ,没有调用者执行空引用检查; 也没有提供一个不受“正常”拳击限制的结构。

如果CLS规范定义了这样的一种方法,那么.net将可能始终如一地遵循由公共对象模型(COM)build立的领导,在这个领导下空string引用被认为在语义上等同于一个空string,用户定义的不可变类types应该具有值语义来同样定义默认值。 从本质上讲,会发生什么会是每个成员的String ,例如Length被写为像[InvokableOnNull()] int String Length { get { if (this==null) return 0; else return _Length;} } [InvokableOnNull()] int String Length { get { if (this==null) return 0; else return _Length;} } 。 这种方法将提供非常好的语义,它应该像值一样行事,但是由于实现问题需要存储在堆上。 这种方法最大的困难在于这种types和Object之间的转换的语义会变得有些模糊。

另一种方法是允许定义不是从Objectinheritance的特殊结构types,而是具有自定义装箱和拆箱操作(可以转换为其他类types)。 在这种方法下,将会有一个types为NullableString行为像现在的string,以及一个定制的结构typesString ,它将保存一个Stringtypes的私有字段Value 。 尝试将String转换为NullableStringObject ,如果为非null,则返回Value如果为null,则返回String.Empty 。 尝试转换为String ,对NullableString实例的非null引用将在Value存储引用(如果长度为零,则可能会存储null); 铸造任何其他的引用会抛出一个exception。

尽pipestring必须存储在堆上,但是概念上没有理由不应该像具有非空默认值的值types那样工作。 把它们作为一个“普通”结构来存储,对于使用它们作为types“string”的代码来说,它是有效的,但是在向“对象”投射时会增加一个额外的间接层和低效率层。 虽然我没有预见到.net在这个迟到的日子里添加了上述任何一个特性,但是未来的框架devise者可能会考虑包含它们。

如果string的默认值是空string,我不必testing

错误! 更改默认值不会改变它是引用types的事实,而且某人仍然可以显式地引用设置为null

此外, Nullable<String>将是有意义的。

真的。 对于任何引用types,不允许为null ,而是需要Nullable<TheRefType>

那么为什么C#的devise者select使用null作为string的默认值呢?

与其他参考types一致。 现在,为什么允许引用types为null ? 大概是这样的感觉就像C,尽pipe这是一个有问题的devise决定,它也提供了Nullable语言。

一个string是一个不可变的对象,这意味着当给定一个值时,旧值不会从内存中消失,而是保留在原来的位置,并将新值置于新的位置。 所以如果String a的默认值是String.Empty ,那么当它被赋予第一个值的时候,会浪费内存中的String.Empty块。

虽然它看起来很小,但在使用String.Empty默认值初始化大量string时,可能会变成问题。 当然,如果这将是一个问题,你总是可以使用可变的StringBuilder类。

由于string是引用types,引用types的默认值为空。

也许如果你使用?? 运算符时分配你的stringvariables,它可能会帮助你。

 string str = SomeMethodThatReturnsaString() ?? ""; // if SomeMethodThatReturnsaString() returns a null value, "" is assigned to str. 

也许string关键字混淆了你,因为它看起来和任何其他的值types声明完全一样,但是它实际上是System.String一个别名,正如在这个问题中所解释的那样。
此外,在Visual Studio中的深蓝色和小写的第一个字母可能会误认为它是一个struct

可空types直到2.0才进入。

如果在该语言的开头已经创build了可为空的types,那么string将是不可空的并且是string的? 本来是可以空的。 但是他们无法做到这一点来向后兼容。

很多人都在谈论ref-type或not reftypes,但是string是一个不寻常的类,解决scheme已经被发现使它成为可能。

我正在做如下

 class myPOCOClass { private string _item1=""; public string item1 { get { return (_item1==null?"":_item1); } set{ _item1=value; } } }