Cannot use String.Empty as a default value for an optional parameter
I am reading Effective C# by Bill Wagner. In Item 14 - Minimize Duplicate Initialization Logic, he shows the following example of using the new optional parameters feature in a constructor:
public MyClass(int initialCount = 0, string name = "")
Notice that he used ""
instead of string.Empty
.
He comments:
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.
If we cannot use the string.Empty
static in all situations, then doesn't that defeat the purpose of it? I thought that we would use it to be sure that we have a system-independent means of referring to the empty string. Is my understanding wrong? Thanks.
UPDATE
Just a follow up comment. According to 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.
Then we aren't be able to use System.Environment.NewLine
either, or use newly instantiated objects as default values. I haven't used VS2010 yet, and this is disappointing!
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.]
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:
string.Empty
it's pointless anyway