Create another empty string in .NET? I apologize if this isn't fit for this site but it is a puzzle, not all that practical, so I thought it would fit.

Take this code:

string s = "";
Console.WriteLine(ReferenceEquals(s, string.Empty));


This will print out true because "" is interned by the JITter at some early point and literals are reused from the interning cache.

The question and puzzle is this:


  How can you initialize s such that
  1. s.Length == 0
  2. ReferenceEquals(s, string.Empty) == false


I've tried the following:

string s = "test".Substring(0, 0); // any arbitrary legal start offset tried
string s = new string(' ', 0);
string s = new string(new char[0]);
string s = CallSomeMethodThatWontBeInlined() + CallSomeMethodThatWontBeInlined();


These three all end up being equal to string.Empty.

Bonus if you can explain the above behavior with regards to new string(...). I have my thoughts about it but no solid evidence one way or another.

I can understand that all methods that concatenate or take substrings of existing strings special-case the result that will end up with length zero, but how new string(...) actually doesn't create a new object I don't know.

Note! I'm asking for legal C#. I'm not asking for a p/invoke or assembly code call that just manually constructs the bytes of an empty string object in memory and stuffs a pointer to it into a string variable.

Any method or path through existing classes in .NET or using operators of strings or whatnot that would end up with the required results are legal. As such, take the Substring example above, if that returned a new empty string that isn't the same as the existing one, then that would be a/the answer to this puzzle.

Reflection is boundary, at the very least it has to be reflection that can run in untrusted scenarios.



My own "conclusion" is that this may indeed be impossible because the actual C# code that would end up constructing such a string would end up with one of the new string(...) overloads, or using one of the operators which all seem to handle this cases. As such, the end-point of any such code may be the one that handles this case and since it does, it may not be possible.
So, I'll take the easy way:

string s = "";


So, s.Length is now 0, so far so good. But how can we get ReferenceEquals(s, string.Empty) to false.

Piece of cake, just put that into your class:

public static new bool ReferenceEquals(object a, object b) =&gt; false;


and the above call will result in false.

I will look for some more sneaky methods, so.