362

In .NET, what is the difference between String.Empty and "", and are they interchangeable, or is there some underlying reference or Localization issues around equality that String.Empty will ensure are not a problem?

Selim Yildiz
5,3806 gold badges21 silver badges34 bronze badges
asked Sep 30, 2008 at 1:59
3
  • 7
    The real question is NOT what rather why. Why Microsoft came up with string.Empty and what was the rationale behind declaring it as readonly instead of const. Commented Jul 7, 2018 at 5:18
  • Several of the answers seem to be geared towards checking whether a string is empty, which is a more specific problem than that of generally using an empty string. Commented Oct 28, 2021 at 15:35
  • Does this answer your question? In C#, should I use string.Empty or String.Empty or "" to intitialize a string? Commented Jan 19, 2023 at 22:55

18 Answers 18

372

In .NET prior to version 2.0, "" creates an object while string.Empty creates no objectref , which makes string.Empty more efficient.

In version 2.0 and later of .NET, all occurrences of "" refer to the same string literal, which means "" is equivalent to .Empty, but still not as fast as .Length == 0.

.Length == 0 is the fastest option, but .Empty makes for slightly cleaner code.

See the .NET specification for more information.

Callum Watkins
3,0204 gold badges33 silver badges54 bronze badges
answered Sep 30, 2008 at 2:02

5 Comments

"" would only have created an object once anyway due to string interning. Basically the performance tradeoff is peanuts - readability is more important.
Interesting that even though the question says nothing about comparing a string to either "" or string.Empty to check for empty strings, a lot of people seem to interpret the question that way...
I would be careful with .Length == 0, as it can throw an exception if your string variable is null. If you check it against "" though, it will just properly return false with no exception.
@JeffreyHarmon: Or you could use string.IsNullOrEmpty( stringVar ).
If anyone wants to prevent bad practices to test for an empty string, you can enable CA1820 in Code Analysis. learn.microsoft.com/visualstudio/code-quality/…
243

what is the difference between String.Empty and "", and are they interchangable

string.Empty is a read-only field whereas "" is a compile time constant. Places where they behave differently are:

Default Parameter value in C# 4.0 or higher

void SomeMethod(int ID, string value = string.Empty)
// Error: Default parameter value for 'value' must be a compile-time constant
{
 //... implementation
}

Case expression in switch statement

string str = "";
switch(str)
{
 case string.Empty: // Error: A constant value is expected. 
 break;
 case "":
 break;
}

Attribute arguments

[Example(String.Empty)]
// Error: An attribute argument must be a constant expression, typeof expression 
// or array creation expression of an attribute parameter type
MagicSeth
4,6152 gold badges29 silver badges16 bronze badges
answered Dec 4, 2012 at 12:39

6 Comments

Interesting, I didn't think this old question would get any relevant new information. I was wrong
I think your example #1 Default Parameter value in C# 4.0 or higher is essentially a duplicate of your example #3 Attribute arguments, since I believe that .NET deploys the default parameters into attributes. So more basically, you simply can't put a (run-time) "value" (in this case, an instance handle, for the sticklers out there) into (compile-time) metadata.
@GlennSlayden, I do not agree with you. Attribute initialization is different from an ordinary initialization. That is because you can pass the String.Empty as an argument in most cases. You are right that all the examples show that you simply can't put a (run-time) "value" into (compile-time) metadata and that is what the examples are aiming to show.
Those don't look like ways in which they behave differently to me. Only situations in which one is legal and the other isn't. Saying that they behave differently, to me, is saying that both constitute legal code but there is potentially different behaviour at runtime depending on which you use.
It would be interesting to know why string.Empty is a readonly field. Seems like the perfect place for a compile-time constant. It's not like string.Empty would ever need to be calculated at runtime, right?
|
48

The previous answers were correct for .NET 1.1 (look at the date of the post they linked: 2003). As of .NET 2.0 and later, there is essentially no difference. The JIT will end up referencing the same object on the heap anyhow.

According to the C# specification, section 2.4.4.5: http://msdn.microsoft.com/en-us/library/aa691090(VS.71).aspx

Each string literal does not necessarily result in a new string instance. When two or more string literals that are equivalent according to the string equality operator (Section 7.9.7) appear in the same assembly, these string literals refer to the same string instance.

Someone even mentions this in the comments of Brad Abram's post

In summary, the practical result of "" vs. String.Empty is nil. The JIT will figure it out in the end.

I have found, personally, that the JIT is way smarter than me and so I try not to get too clever with micro-compiler optimizations like that. The JIT will unfold for() loops, remove redundant code, inline methods, etc better and at more appropriate times than either I or the C# compiler could ever anticipate before hand. Let the JIT do its job :)

user3797758
1,1131 gold badge18 silver badges36 bronze badges
answered Sep 30, 2008 at 2:19

2 Comments

Related popular question stackoverflow.com/questions/263191/…
43

String.Empty is a readonly field while "" is a const. This means you can't use String.Empty in a switch statement because it is not a constant.

shA.t
17k5 gold badges59 silver badges120 bronze badges
answered Oct 1, 2008 at 3:18

2 Comments

with the advent of the default keyword we can promote readability without, prevent accidental modification, and have a compile-time constant, though to be honest, I still think String.Empty is more readable than default, but slower to type
@Enzoaeneas A default string is null, not empty. The default to all reference objects is null.
26

I tend to use String.Empty rather than "" for one simple, yet not obvious reason: "" and "" are NOT the same, the first one actually has 16 zero width characters in it. Obviously no competent developer is going to put and zero width characters into their code, but if they do get in there, it can be a maintenance nightmare.

Notes:

  • I used U+FEFF in this example.

  • Not sure if SO is going to eat those characters, but try it yourself with one of the many zero-width characters

  • I only came upon this thanks to https://codegolf.stackexchange.com/

answered Nov 25, 2015 at 11:42

4 Comments

This deserves more upvotes. I've seen this problem occur via system integration across platforms.
To me, this is a bad code style. You should use "\xfeff" to add invisible characters.
@VasiliyZverev Yes having literal zero-width characters in your code would not be a good idea in general, the point is copy-pasting from somewhere else, and not realising it had the zero-width characters in it. Something like StyleCop, could probably be configured to flag things like this, but not every[one/ project] will be setup with it.
that's nonsense. Such strings should be accompanied by a comment (or immediately obvious variable name, etc) otherwise it'll just be confusing. If you're worried about zero width characters slipping in from copy pasting, simply using String.Empty doesn't do anything about them getting into something like "somestring".
18

Another difference is that String.Empty generates larger CIL code. While the code for referencing "" and String.Empty is the same length, the compiler doesn't optimize string concatenation (see Eric Lippert's blog post) for String.Empty arguments. The following equivalent functions

string foo()
{
 return "foo" + "";
}
string bar()
{
 return "bar" + string.Empty;
}

generate this IL

.method private hidebysig instance string foo() cil managed
{
 .maxstack 8
 L_0000: ldstr "foo"
 L_0005: ret 
}
.method private hidebysig instance string bar() cil managed
{
 .maxstack 8
 L_0000: ldstr "bar"
 L_0005: ldsfld string [mscorlib]System.String::Empty
 L_000a: call string [mscorlib]System.String::Concat(string, string)
 L_000f: ret 
}
answered Jun 30, 2013 at 2:07

4 Comments

Valid point but who would do such thing? Why should I concatenate an empty string to something on purpose?
@RobertS. Maybe the second string was in a separate function that got inlined. It's rare, I grant you.
it's not that rare using the ternary operator: "bar " + (ok ? "" : "error")
But in the case of a ternary operator, unless ok is a compile-time constant, the resulting IL will need to use string.Concat anyway.
12

The above answers are technically correct, but what you may really want to use, for best code readability and least chance of an exception is String.IsNullOrEmpty(s)

answered Sep 30, 2008 at 4:06

2 Comments

In terms of equality comparison, I completely agree, but the question was also about the difference between the two concepts as well as comparison
Beware that "least chance of an exception" often means "most chance of continuing but doing something wrong". For example, if you have a command line argument you are parsing and someone calls your app with --foo=$BAR then you probably want to spot the difference between them forgetting to set an env var and them not passing the flag in at all. string.IsNullOrEmpty is often a code-smell that you have not validated your inputs properly or are doing weird things. You shouldn't generally accept empty strings when you really mean to use null, or something like a Maybe / Option type.
7

All instances of "" are the same, interned string literal (or they should be). So you really won't be throwing a new object on the heap every time you use "" but just creating a reference to the same, interned object. Having said that, I prefer string.Empty. I think it makes code more readable.

answered Sep 30, 2008 at 2:08

Comments

5

String.Empty does not create an object whereas "" does. The difference, as pointed out here, is trivial, however.

answered Sep 30, 2008 at 2:02

3 Comments

It isn't trivial if you check a string for string.Empty or "". One should really use String.IsNullOrEmpty as Eugene Katz pointed out. Otherwise you will get unexpected results.
@Sigur How do you use String.IsNullOrEmpty to set a variable to an empty string, or to pass an empty string as a function argument?
To set a string to empty use String.Empty. To check for an empty string use String.IsNullOrEmpty. Note that String.IsNullOrEmpty is a double check either of which belong to different domains. To Check for null is a technical check to avoid crashes, while checking for empty is a functional check. An empty string could be a valid value. So checking for it is usually done on different places in the code.
5

Use String.Empty rather than "".

This is more for speed than memory usage but it is a useful tip. The "" is a literal so will act as a literal: on the first use it is created and for the following uses its reference is returned. Only one instance of "" will be stored in memory no matter how many times we use it! I don't see any memory penalties here. The problem is that each time the "" is used, a comparing loop is executed to check if the "" is already in the intern pool. On the other side, String.Empty is a reference to a "" stored in the .NET Framework memory zone. String.Empty is pointing to same memory address for VB.NET and C# applications. So why search for a reference each time you need "" when you have that reference in String.Empty?

Reference: String.Empty vs ""

shA.t
17k5 gold badges59 silver badges120 bronze badges
answered Feb 11, 2016 at 9:20

2 Comments

This hasn't been true since .net 2.0
This searching for a reference, if it's needed, would surely happen at compile time, so the runtime overhead would be zero. But I would probably expect even better: to recognise "" as being the same as string.Empty and thereby be able to emit the correct reference instantly.
4
string mystring = "";
ldstr ""

ldstr pushes a new object reference to a string literal stored in the metadata.

string mystring = String.Empty;
ldsfld string [mscorlib]System.String::Empty

ldsfld pushes the value of a static field onto the evaluation stack

I tend to use String.Empty instead of "" because IMHO it's clearer and less VB-ish.

Marco Bonelli
70.7k21 gold badges129 silver badges152 bronze badges
answered Apr 17, 2015 at 16:34

Comments

3

When you're visually scanning through code, "" appears colorized the way strings are colorized. string.Empty looks like a regular class-member-access. During a quick look, its easier to spot "" or intuit the meaning.

Spot the strings (stack overflow colorization isn't exactly helping, but in VS this is more obvious):

var i = 30;
var f = Math.Pi;
var s = "";
var d = 22.2m;
var t = "I am some text";
var e = string.Empty;
answered May 7, 2019 at 13:58

2 Comments

You make a good point, but did the developer really mean ""? Perhaps they meant to put in some as yet unknown value and forgot to return? string.Empty has the advantage of giving you confidence that the original author really meant string.Empty. Its a minor point I know.
Also, a malicious (or careless) developer may put a zero-width character between the quotes instead of using the appropriate escape sequence like \u00ad.
3

Eric Lippert wrote (June 17, 2013):
"The first algorithm I ever worked on in the C# compiler was the optimizer that handles string concatenations. Unfortunately I did not manage to port these optimizations to the Roslyn codebase before I left; hopefully someone will get to that!"

Here are some Roslyn x64 results as of January 2019. Despite the consensus remarks of the other answers on this page, it does not appear to me that the current x64 JIT is treating all of these cases identically, when all is said and done.

Note in particular, however, that only one of these examples actually ends up calling String.Concat, and I'm guessing that that's for obscure correctness reasons (as opposed to an optimization oversight). The other differences seem harder to explain.


default(String) + { default(String), "", String.Empty }

static String s00() => default(String) + default(String);
 mov rax,[String::Empty]
 mov rax,qword ptr [rax]
 add rsp,28h
 ret
static String s01() => default(String) + "";
 mov rax,[String::Empty]
 mov rax,qword ptr [rax]
 add rsp,28h
 ret
static String s02() => default(String) + String.Empty;
 mov rax,[String::Empty]
 mov rax,qword ptr [rax]
 mov rdx,rax
 test rdx,rdx
 jne _L
 mov rdx,rax
_L: mov rax,rdx
 add rsp,28h
 ret

"" + { default(String), "", String.Empty }

static String s03() => "" + default(String);
 mov rax,[String::Empty]
 mov rax,qword ptr [rax]
 add rsp,28h
 ret
static String s04() => "" + "";
 mov rax,[String::Empty]
 mov rax,qword ptr [rax]
 add rsp,28h
 ret
static String s05() => "" + String.Empty;
 mov rax,[String::Empty]
 mov rax,qword ptr [rax]
 mov rdx,rax
 test rdx,rdx
 jne _L
 mov rdx,rax
_L: mov rax,rdx
 add rsp,28h
 ret

String.Empty + { default(String), "", String.Empty }

static String s06() => String.Empty + default(String);
 mov rax,[String::Empty]
 mov rax,qword ptr [rax]
 mov rdx,rax
 test rdx,rdx
 jne _L
 mov rdx,rax
_L: mov rax,rdx
 add rsp,28h
 ret
static String s07() => String.Empty + "";
 mov rax,[String::Empty]
 mov rax,qword ptr [rax]
 mov rdx,rax
 test rdx,rdx
 jne _L
 mov rdx,rax
_L: mov rax,rdx
 add rsp,28h
 ret
static String s08() => String.Empty + String.Empty;
 mov rcx,[String::Empty]
 mov rcx,qword ptr [rcx]
 mov qword ptr [rsp+20h],rcx
 mov rcx,qword ptr [rsp+20h]
 mov rdx,qword ptr [rsp+20h]
 call F330CF60 ; <-- String.Concat
 nop
 add rsp,28h
 ret


Test details

Microsoft (R) Visual C# Compiler version 2.10.0.0 (b9fb1610)
AMD64 Release
[MethodImpl(MethodImplOptions.NoInlining)]
'SuppressJitOptimization' = false
answered Jan 31, 2019 at 4:42

1 Comment

A quick check using sharplab.io shows that Core CLR 6.0.21.52210 treats s00 through s07 the same (with code generated matching your s00 here), but still uses String.Concat() for s08.
2

Coming at this from an Entity Framework point of view: EF versions 6.1.3 appears to treat String.Empty and "" differently when validating.

string.Empty is treated as a null value for validation purposes and will throw a validation error if it's used on a Required (attributed) field; where as "" will pass validation and not throw the error.

This problem may be resolved in EF 7+. Reference: - https://github.com/aspnet/EntityFramework/issues/2610 ).

Edit: [Required(AllowEmptyStrings = true)] will resolve this issue, allowing string.Empty to validate.

answered Mar 9, 2017 at 11:59

Comments

2

Since String.Empty is not a compile-time constant you cannot use it as a default value in function definition.

public void test(int i=0,string s="")
 {
 // Function Body
 }
answered Mar 14, 2017 at 7:11

1 Comment

Just the summary from this answer: public void test(int i=0, string s=string.Empty) {} will not compile and say "Default parameter value for 's' must be a compile-time constant. OP’s answer works.
1

Use string.Empty in most cases for readability. Some developer's vision might not be able to tell the difference of "" and " ", where string.Empty is clear.

For parameter defaults will still have to use "", but in that case, I wonder why the method does not use string? = null instead for a defaulted param.(also more readable for the visually impared)

answered Aug 9, 2023 at 14:28

Comments

-1

Thanks for a very informative answer.

Forgive my ignorance if I'm wrong. I'm using VB but I think if you test the length of an unassigned string (i.e. IS Nothing), it returns an error. Now, I started programming in 1969, so I've been left well behind, however I have always tested strings by concatenating an empty string (""). E.g. (in whatever language): -

if string + "" = ""

answered Mar 12, 2021 at 17:48

Comments

-12

Everybody here gave some good theoretical clarification. I had a similar doubt. So I tried a basic coding on it. And I found a difference. Here's the difference.

string str=null;
Console.WriteLine(str.Length); // Exception(NullRefernceException) for pointing to null reference. 
string str = string.Empty;
Console.WriteLine(str.Length); // 0

So it seems "Null" means absolutely void & "String.Empty" means It contains some kind of value, but it is empty.

Rick Smith
9,29916 gold badges85 silver badges86 bronze badges
answered Jan 21, 2016 at 15:57

1 Comment

Note that the question is about "" versus string.Empty. Only when trying to tell if string is empty, null had been mentioned.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.