不能将 String.Empty 用作可选参数的默认值

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

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

注意,他使用的是 ""而不是 string.Empty
他评论道:

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

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

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

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

那么我们也不能使用 System.Environment.NewLine,或者使用新实例化的对象作为默认值。我还没有使用 VS2010,这是令人失望的!

51012 次浏览

I never use string.Empty, I can't see the point of it. Maybe it makes it easier for people that are really new to programming, but I doubt it's useful even for that.

I think the idea behind string.Empty is it enhances readability. It is not like newline where there is any difference between how it is represented on different platforms. It's ashame it can't be used in a default parameter. However, it will not cause any issues if you port between Windows and something like Mono on Linux.

As of the C# 2.0 compiler, there is very little point to String.Empty anyway, and in fact in many cases it's a pessimisation, since the compiler can inline some references to "" but can't do the same with String.Empty.

In C# 1.1 it was useful to avoid creating lots of independent objects all containing the empty string, but those days are gone. "" works just fine.

There's nothing to stop you from defining your own constant for the empty string if you really want to use it as an optional parameter value:

const string String_Empty = "";


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

[As an aside, one reason to prefer String.Empty over "" in general, that hasn't been mentioned in the other answers, is that there are various Unicode characters (zero-width joiners, etc.) that are effectively invisible to the naked eye. So something that looks like "" isn't necessarily the empty string, whereas with String.Empty you know exactly what you're using. I recognise this isn't a common source of bugs, but it is possible.]

As a FYI, it looks like the same constraint is imposed on values passed to attribute constructors - they must be constant. Since string.empty is defined as :

public static readonly string Empty

rather than an actual constant, it cannot be used.

From the original question:

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

In what way can the empty string vary from system to system? It's always a string with no characters! I'd be really scared if I ever found an implementation where string.Empty == "" returned false :) This is not the same as something like Environment.NewLine.

From Counter Terrorist's bounty post:

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

Well that's certainly not going to happen.

While I would personally have liked a very different defaulting mechanism too, the way optional parameters work has been in .NET since the start - and it always means embedding a constant into the metadata, so that the calling code can copy that constant into the call site if no corresponding argument is provided.

With string.Empty it's really pointless - using "" will do what you want; is it that painful to use the string literal? (I use the literal everywhere - I never use string.Empty - but that's a different argument.)

That's what surprises me about this question - the complaint revolves around something which doesn't actually cause a real problem. It's for more important in cases where you want the default to be computed at execution time because it might actually vary. For example, I could imagine cases where you want to be able to call a method with a DateTime parameter and have it default to "the current time". At the moment, the only vaguely elegant workaround I know for that is:

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

... but that's not always appropriate.

In conclusion:

  • I very much doubt that this will ever be part of C#
  • For string.Empty it's pointless anyway
  • For other values which really don't always have the same value, it really can be a pain

I use string.Empty purely for readability.

If someone else needs to read/change my code later they know that I meant to check for or set something to an empty string. Using just "" can sometimes cause bugs and confusion because I may have just forgot to put the string that I wanted in there.

For example:

if(someString == string.Empty)
{


}

vs

if(someString == "")
{


}

The first if statement just seems so much more deliberate and readable to me. Because this is just a preference though, I really do not see the train-smash in having to use "" instead of string.Empty.