How to manufacture an empty string in .NET?
There is no true 100% supported way of manufacturing a fresh zero-length string in .NET. As an implementation detail, existing string APIs may try to normalize zero-length return values to the instance string.Empty
, but whether or not they do this consistently isn't something a developer should be relying on.
In particular, the other two answers have problems:
The
string.Copy
solution even includes the caveat that the method is obsolete in .NET Core 3.0. The method is likely to be removed entirely from a future version of .NET Core, so any solution which relies on callingstring.Copy
is going to break when the application eventually moves on to the new version of the runtime.The
FastAllocateString
solution takes a dependency on an undocumented, internal API within the runtime. Internal APIs aren't guaranteed to stick around between versions. In fact, we're planning major changes in the way strings behave in the next version of .NET, and that work will almost certainly affect this internal API.
So, to your particular question as to whether there's a reliable way to manufacture a fresh zero-length string instance, the answer is no.
If you want to special-case zero-length strings in your code, the best solution would be to use the pattern if (myString.Length == 0) { /* ... */ }
. The patterns if (myString == string.Empty) { /* ... */ }
and if (myString == "") { /* ... */ }
will also work, but their codegen won't be as optimized as the first proposal.
If you want to special-case null or empty strings, the best solution would be to use the existing string.IsNullOrEmpty
API. The implementation of this method changes from version to version to take advantage of whatever JIT optimizations are available at the time.
Source: I am one of the primary developers on the System.String class.
You can use the Obsolete method String.Copy
string s1 = "";
string s2 = String.Copy("");
Assert.IsTrue(s1.Length == 0 && s2.Length == 0);
Assert.IsTrue(!ReferenceEquals(s1, s2));
You can use FastAllocateString
method for that (it's being used internally in String
and StringBuilder
classes). Since it has internal static
modifier, you should use reflection to invoke. But it returns two different empty strings in a memory
var fastAllocate = typeof(string).GetMethods(BindingFlags.NonPublic | BindingFlags.Static)
.First(x => x.Name == "FastAllocateString");
string s1 = (string)fastAllocate.Invoke(null, new object[] { 0 });
string s2 = (string)fastAllocate.Invoke(null, new object[] { 0 });
var zeroLength = s1.Length == 0 && s2.Length == 0;
var notEqual = !ReferenceEquals(s1, s2);
Both checks returns true
here