无法将String.Empty用作可选参数的默认值


89

我正在阅读Bill Wagner撰写的Effective C#。在第14项-最小化重复初始化逻辑中,他显示了以下在构造函数中使用新的可选参数功能的示例:

public MyClass(int initialCount = 0, string name = "")

请注意,他使用""代替string.Empty
他评论:

您会注意到[在上面的示例中]第二个构造函数在name参数上为默认值指定了“” ,而不是更习惯的string.Empty。那是因为string.Empty不是编译时常量。它是在字符串类中定义的静态属性。因为它不是编译常量,所以不能将其用作参数的默认值。

如果我们不能string.Empty在所有情况下都使用静态,那这是否会破坏其目的?我认为我们将使用它来确保我们有一种独立于系统的方式来引用空字符串。我的理解错了吗?谢谢。

更新
只是后续评论。根据MSDN:

每个可选参数都有一个默认值作为其定义的一部分。如果没有为该参数发送参数,则使用默认值。默认值必须是常量。

这样一来,我们将无法使用System.Environment.NewLine或使用新实例化的对象作为默认值。我还没有使用过VS2010,这真令人失望!


2
我不知道在不同平台上如何表示空字符串之间的任何区别。它不像换行符。
Tom Cabanski 2010年

是的,我当时在想,那么仅仅是代码看起来更好吗?
Mikeyg36 2010年

1
CLR而非“系统”是确定“”是否为空字符串的决定因素。因此,我认为您可以放心地假设“”是在兼容的CLR实现中引用字符串的系统独立方式。
克里斯·泰勒

“与系统无关”?er,而不是系统特定的“”?(???)
Qwertie

根据MSDN:此字段的值为零长度字符串“”。因此,正如许多人指出的那样,它显然与平台独立性无关。但是似乎人们仍然不知道为什么应该使用它!
Mikeyg36 2010年

Answers:


65

对于C#2.0编译器,String.Empty无论如何都没有什么意义,实际上,在很多情况下,这是一种悲观的说法,因为编译器可以内联某些引用,""但不能使用进行相同的引用String.Empty

在C#1.1中,避免创建很多都包含空字符串的独立对象很有用,但是那些日子已经一去不复返了。 ""效果很好。


7
即使在.NET 1.1中,它也不会创建独立对象的“很多”。我不记得在这方面1.1和2.0之间的区别的细节,但这不像字符串文字实习仅在2.0中引入。
乔恩·斯基特

感谢您的澄清。我环顾了一下,但没有找到关于C#2.0更改的完整摘要,尽管我敢肯定我以前已经读过一篇。我确实找到了2008年的StackOverflow答案,其中包含一些指向更多技术信息的链接。 stackoverflow.com/questions/151472/…–
安迪·莫蒂默

1
我会点头,尽管我不喜欢说string没有什么意义。因为我经常使用它,所以很空。我发现它看起来更干净,尽管这是我个人的看法。在很多地方都有string.Empty不能使用,在这种情况下使用“”也没有问题
xximjasonxx,2010年

14
我发现,使用String.Empty快速识别一个空字符串要比两次查看“”来确保它没有撇号或类似的东西要容易得多。+1虽然解释。
NotMe 2011年

11
+1克里斯。同样在VS中,您实际上无法搜索“”的用法(除了进行标准的Find(查找)之外,它还会带回每个文本匹配项,包括注释和标记)。您可以使用string.Empty搜索特定于代码的用法。
MutantNinjaCodeMonkey '02年

53

如果您真的想将其用作可选参数值,则可以阻止您为空字符串定义自己的常量:

const string String_Empty = "";

public static void PrintString(string s = String_Empty)
{
    Console.WriteLine(s);
}

[顺便说一句,一个理由,更喜欢String.Empty""在一般情况下,还没有在其他的答案所提到的,是有是有效不可见的肉眼各种Unicode字符(零宽度加入者等)。因此,看起来像""不一定是空字符串,而String.Empty您却知道自己在使用什么。我知道这不是错误的常见来源,但是有可能。]


2
还有不可见的标识符字符,因此不一定像String_Empty那样。Unicode标准在安全性考虑方面有一章被忽略的章节。
吉姆·巴尔特

25

从最初的问题:

我认为我们将使用它来确保我们拥有一种与系统无关的方式来引用空字符串。

空字符串可以通过什么方式随系统而变化?它始终是没有字符的字符串!我会真的吓坏了,如果我没有发现其中的实现string.Empty == ""返回false :)这是一样的东西一样Environment.NewLine

从反恐怖组织的赏金帖子中:

我希望String.Empty可以在下一个C#版本中用作默认参数。:D

好吧,那肯定不会发生。

虽然我个人也会喜欢非常不同的默认机制,但是自开始以来,可选参数的工作方式就一直在.NET中-它始终意味着将常量嵌入到元数据中,以便调用代码可以将该常量复制到调用中如果未提供相应的参数,则为站点。

有了string.Empty真的是没有意义的-使用""将做您想要的;使用字符串文字会不会痛苦?(我在所有地方都使用文字-我从未使用过string.Empty-但这是一个不同的论点。)

这使我对此问题感到惊讶-投诉围绕实际上没有引起真正问题的事情。在您希望在执行时计算默认值的情况下,这一点尤为重要,因为它实际上可能会有所不同。例如,我可以想象一下您希望能够使用DateTime参数调用方法并将其默认设置为“当前时间”的情况。目前,我知道的唯一模糊的解决方法是:

public void RecordTime(string message, DateTime? dateTime = null)
{
    var realDateTime = dateTime ?? DateTime.UtcNow;
}

...但这并不总是合适的。

结论:

  • 我非常怀疑这是否会成为C#的一部分
  • 因为string.Empty它毫无意义
  • 对于实际上并非总是具有相同值的其他值,这确实很痛苦

这实际上是解决问题的一种好方法。可以使用同一件事来承载/设置其他与设备相关的变量,例如Environment.Newline..您的示例中唯一缺少的是检查该变量是否为null,并向开发人员抛出异常,告诉他虽然该变量可为null,但是不接受。if(dateTime == null){ throw new ArgumentException("The dateTime parameter must be set. Nullable type used for device independent variable set.");}或类似的东西。但是我真的很喜欢这个!还有其他需要注意的注意事项吗?
MaxOvrdrv 2014年

@MaxOvrdrv:您不希望将null设置为错误-重点是当它为null时,您将计算默认值。需要注意的是,它本身不允许将null作为有效值传递。
乔恩·斯基特

您对此完全正确。我的错。-是的,那是唯一真正的警告,不是吗……那还不错。再说一次:我真的很喜欢这个解决方案!:)感谢您发布它!:)
MaxOvrdrv 2014年

7

我从不使用string.Empty,我看不到它的意义。也许它使真正接触编程的人变得更容易,但是我怀疑这样做是否有用。


2
也许它可以防止""和混淆" ",但是我不能说这" "很普遍。
格雷格

8
我建议任何无法分辨两者之间差异的人都需要更好的眼镜或降低屏幕分辨率。我的视力不好,也记不起曾经犯过这个错误(而且我必须处理很多包含这两个错误的代码)。
汉斯·奥尔森,2010年

2
string.Empty有助于找出程序员的确切意图。“”没有说明任何意图,如果程序员的意图是像这样“ lol”那样初始化变量,却忘记了……在这种情况下,存在无穷的可能性和字符串,Empty派上用场,并且做得更好
有用的蜜蜂

4

我认为string.Empty背后的想法是提高可读性。它与换行符不同,它在不同平台上的表示方式也不相同。很遗憾,它不能在默认参数中使用。但是,如果您在Windows和Linux上的Mono之类的端口之间进行移植,则不会造成任何问题。


5
我认为您可能是对的,关键是有些人认为String.Empty更具可读性。。。不过,就我个人而言,我认为这有点坚果。""可能是最常见的字符串,并且每个人都看过十亿次,那么它怎么不可读?String.Empty就像有一个Int32.Zero
Tim Goodman 2010年

3

作为FYI,似乎对传递给属性构造函数的值施加了相同的约束-它们必须恒定。由于string.empty定义为:

public static readonly string Empty

而不是实际常数,因此无法使用。


1

string.Empty纯粹是为了提高可读性。

如果以后有人需要阅读/更改我的代码,他们会知道我要检查或设置一个空字符串。使用just ""有时会导致错误和混乱,因为我可能只是忘了把想要的字符串放在那儿了。

例如:

if(someString == string.Empty)
{

}

if(someString == "")
{

}

if对我来说,第一个声明似乎更加深思熟虑。因为这不过是一种偏爱,所以我真的看不到必须使用""代替代替的用法string.Empty


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.