Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to manufacture an empty string in .NET?

Tags:

string

c#

.net

I have written a piece of optimized code that contains special cases for null and empty strings. I am now trying to write a unit test for this code. In order to do that, I need two empty (zero-length) string objects that are different objects. Like this:

string s1, s2;
Assert.IsTrue(s1.Length == 0 && s2.Length == 0);
Assert.IsTrue(!ReferenceEquals(s1, s2));

It turns out that most .NET Framework APIs string are checking for an empty result. They are returning string.Empty in all those cases. For example, "x".Remove(0, 1) returns string.Empty.

How can I create fresh zero-length string objects?

like image 792
boot4life Avatar asked Feb 13 '20 17:02

boot4life


2 Answers

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 calling string.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.

like image 122
Levi Avatar answered Oct 21 '22 20:10

Levi


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));
like image 25
jbtule Avatar answered Oct 21 '22 20:10

jbtule