关于c#:不能将String.Empty用作可选参数的默认值

Cannot use String.Empty as a default value for an optional parameter

我在读比尔·瓦格纳的《有效C》。在项目14-最小化重复初始化逻辑中,他展示了在构造函数中使用新的可选参数特性的以下示例:

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

注意他用了""而不是string.Empty。他评论说:

You'll note [in an example above] that the second constructor specified"" for the default value on the name parameter, rather than the more customary string.Empty. That's because string.Empty is not a compile-time constant. It is a static property defined in the string class. Because it is not a compile constant, you cannot use it for the default value for a parameter.

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

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

Each optional parameter has a default value as part of its definition. If no argument is sent for that parameter, the default value is used. Default values must be constants.

然后我们也不能使用System.Environment.NewLine,或者使用新实例化的对象作为默认值。我还没用过VS2010,这真让人失望!


对于C 2.0编译器,几乎没有指向String.Empty,事实上,在许多情况下,它是悲观的,因为编译器可以内联一些对""的引用,但不能对String.Empty执行相同的操作。

在C 1.1中,避免创建大量独立的对象(所有这些对象都包含空字符串)是很有用的,但是那些日子已经过去了。""工作得很好。


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

1
2
3
4
5
6
const string String_Empty ="";

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

[顺便说一句,一个原因是喜欢String.Empty"",一般来说,在其他答案中没有提到,是有各种Unicode字符(零宽度连接符等)是有效地肉眼看不见的。所以看起来像""的东西不一定是空字符串,而对于String.Empty,你确切地知道你在使用什么。我认识到这不是常见的bug源,但这是可能的。]


从最初的问题:

I thought that we would use it to be sure that we have a system-independent means of referring to the empty string.

空字符串在不同系统中有什么不同?它总是一个没有字符的字符串!如果我发现一个实现中string.Empty ==""返回了false:)这与Environment.NewLine不同,我会非常害怕。

从反恐组织的赏金岗位:

I want String.Empty can be used as a default parameter in the next C# release. :D

那当然不会发生。

虽然我个人也希望使用一种完全不同的默认机制,但自启动以来可选参数在.NET中的工作方式始终意味着在元数据中嵌入常量,以便调用代码可以在没有提供相应参数的情况下将该常量复制到调用站点。

对于String.Empty,使用""会满足您的需要,使用字符串文字会很痛苦吗?(我在任何地方都使用文字-我从未使用过String.Empty,但这是另一种说法。)

这就是我对这个问题感到惊讶的地方——抱怨的焦点是一些实际上不会引起真正问题的事情。在您希望在执行时计算默认值的情况下,这一点更为重要,因为它实际上可能会有所不同。例如,我可以想象这样的情况,您希望能够使用DateTime参数调用一个方法,并将其默认为"当前时间"。目前,我所知道的唯一一个模糊优雅的工作环境是:

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

…但这并不总是合适的。

总之:

  • 我非常怀疑这是否会成为C的一部分。#
  • String.Empty来说,无论如何都是毫无意义的。
  • 对于其他价值观来说,它们的价值并不总是相同的,这确实是一种痛苦。


我从不用绳子。空的,我看不出它的意义。也许它可以让那些刚开始编程的人更容易一些,但我怀疑它是否有用。


我认为字符串背后的想法。空的是它增强了可读性。它不像newline那样,在不同的平台上表示它的方式有任何区别。它是asname,不能在默认参数中使用。但是,如果您在Windows和Linux上的Mono之类的设备之间进行端口连接,则不会导致任何问题。


作为Fyi,似乎对传递给属性构造函数的值施加了相同的约束——它们必须是常量。因为string.empty被定义为:

1
public static readonly string Empty

它不能被使用,而不是实际的常量。


我使用string.Empty纯粹是为了可读性。

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

例如:

1
2
3
4
if(someString == string.Empty)
{

}

VS

1
2
3
4
if(someString =="")
{

}

第一个if声明对我来说似乎更为慎重和易读。因为这只是一种偏好,所以我真的不认为火车会因为使用""而不是string.Empty而崩溃。


也许这个问题的最佳解决方案是通过这种方式重载这个方法:

1
2
3
4
public static void PrintString()
{
    PrintString(string.Empty);
}