3/02/2010

String.Empty vs “” vs String. IsNullOrEmpty

I was reading up on this recently and a couple of interesting points came to light:

myString = “” creates a new instance of type String.

myString = String.Empty does not.

The key item is doing comparisons. Here’s some sample test code:


  
class Program {
static void Main(string[] args)
{
String myString = "";
long a, b, c, d, e, f;
Console.WriteLine("Method 1...");
a = DateTime.Now.Ticks;
for (int index = 0; index < 100000000; index++)
{
bool isEmpty = myString == "";
}
b = DateTime.Now.Ticks;
Console.WriteLine("Method 2...");
c = DateTime.Now.Ticks;
for (int index = 0; index < 100000000; index++)
{
bool isEmpty = myString.Length == 0;
}
d = DateTime.Now.Ticks;
Console.WriteLine("Method 3...");
e = DateTime.Now.Ticks;
for (int index = 0; index < 100000000; index++)
{
bool isEmpty = String.IsNullOrEmpty(myString);
}
f = DateTime.Now.Ticks;
var Method1 = b - a;
var Method2 = d - c;
var Method3 = f - e;
Console.WriteLine("Method 1: bool isEmpty = myString == \"\" took {0} ticks", Method1);
Console.WriteLine("Method 2: bool isEmpty = myString.Length == 0; took {0} ticks", Method2);
Console.WriteLine("Method 3: bool isEmpty = String.IsNullOrEmpty(myString) took {0} ticks", Method3);
Console.Read();
}
}



The results:

Method 1: bool isEmpty = myString == "" took 4836000 ticks
Method 2: bool isEmpty = myString.Length == 0; took 2340000 ticks
Method 3: bool isEmpty = String.IsNullOrEmpty(myString) took 3744000 ticks

Bottom Line? The consensus among at least 4 or 5 expert Tweeters who commented was, IsNullOrEmpty is worth the extra ticks to test for null, even with 10 million iterations in the test!

Note: At the request of Todd Spatafore, I did a Visual Studio 2010 .NET 4.0 app that adds “String.IsNullOrWhitespace”. It performed the worst of all. You can download the VS2010 test solution here:

N.B. Jeremy commented to try:


I did this and it actually ran faster than bool isEmpty =myString.Length == 0;

so you could use this and achieve the need to test for null, and still be the fastest of the three methods shown.

12 comments:

  1. Oddly enough, on my system IsNullOrEmpty often takes less time to complete than comparing to "", no mather what order I run the tests in. Also, comparing to String.Empty seems to be a bit faster than to "".

    I just prefer using IsNullOrEmpty because it offers additional security against null values, where otherwise your code would fail (test n°2 in this example).

    ReplyDelete
  2. Jeremy Gray12:29 PM

    It would be interesting to see the results of another test run where the comparison against an empty string, whether from "" or String.Empty, and the comparison against the string's length were both preceded by a comparison of the string being null. eg:

    bool isEmpty = myString == null || myString.Length == 0;

    That would put the benchmarks on the same functional level with the one for String.IsNullOrEmpty.

    ReplyDelete
  3. @Jeremy,
    bool isEmpty = (myString == null || myString.Length == 0);

    seems to run faster than
    bool isEmpty = myString.Length == 0);

    Interestingly, the decompiled signature of String.IsNullOrEmpty looks like this:

    public static bool IsNullOrEmpty(string value)
    {
    if (value != null)
    {
    return (value.Length == 0);
    }
    return true;
    }

    ReplyDelete
  4. The code from string.IsNullOrEmpty as viewed from Reflector.

    public static bool IsNullOrEmpty(string value)
    {
    if (value != null)
    {
    return (value.Length == 0);
    }
    return true;
    }

    ReplyDelete
  5. @Cory,
    Thanks - Already did that - its in one of the comments above yours!

    ReplyDelete
  6. In code like this performance is almost never a bottleneck.
    Almost always primary concern in such code should be code readability (shorter version is better) and maintainability (IsNullOrEmpty is usually better).

    ReplyDelete
  7. Anonymous3:19 PM

    Actually I tried this on several machines and just couldn't verify these results.

    I called the method several times (10000+) and wrote the results into a table. No matter what I do, IsNullOrEmpty needs fewest ticks...

    ReplyDelete
  8. Try 10 million or even 100 million iterations.

    ReplyDelete
  9. Jeremy Gray4:13 PM

    I'd have to check, but I suspect (and would love for it to be true) that IsNullOrEmpty calls fit the JITter's rules for inlining, which would certainly account for it being just as fast as the explicit null check variations options I mentioned earlier. Oh, the joys of micro-optimization. :)

    ReplyDelete
  10. @Jeremy,
    We were actually discussing this very theory on Twitter. I'm too lazy to decompile and examine the IL :-)

    ReplyDelete
  11. Anonymous12:00 PM

    вот как надо с умным видом заниматся хренью, ага

    Actually, myString = “” does not create any new instances.
    var a = "sometext";
    var b = "sometext";
    reference a will be equal to reference b, not just because of overrided operator==. csc joins equal string constans.
    A good code optimizer should even understand that myString does not change through the loop and ommit multiple comparation with constant. But csc does not.

    By the way, String.IsNullOrEmpty can be inlined during jit'ting. Hence the results can be differnet without debugger, with release build and with optimization.

    Anyway, this kind of optimization won't ever change anything.

    Cheers,
    Andrey.

    ReplyDelete
  12. public void Test()
    {
    string str1 = ""; // this Does create a new object
    for (int i=0; i < 1000; i++)
    {
    string str2 = ""; // these do not - they refer to the interned string str1
    }
    }
    .On invoking Test only one memory heap allocation takes place for the empty string that is only at
    string str1 = "";

    ReplyDelete