string.IsNullOrEmpty是否存在性能问题?

时间:2013-08-26 14:46:59

标签: c#

这两种检查字符串的方法有什么区别吗?

if(!string.IsNullOrEmpty(myString))
{
  //Do something
}

if(myString != null && myString != "")
{
  //Do something
}

到目前为止,我虽然没有,但有人这样说。并且他说第二个更好,因为第一个需要方法调用。

我有点困惑。

7 个答案:

答案 0 :(得分:13)

不,它没有性能问题。以下是它的实现方式:

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

我总是使用IsNullOrEmpty而不是手动编写2个条件。它更具可读性,并且没有与使用它相关的性能成本。

答案 1 :(得分:7)

与其他所有回答的人一样,我认为没有任何性能差异,但为了确保我运行了一个基准测试。结果并不完全符合我的预期......

以下是我的基准测试的代码:

using System;
using System.Diagnostics;

static class Program
{
    static void Main()
    {
        int count = 1;

        // First run for JIT warm-up
        IsNullOrEmpty(null, count);
        TestEqualsEmpty(null, count);
        TestLengthZero(null, count);

        count = 1000000000;

        Console.WriteLine("Case 1: s == \"test\"");
        RunTests("test", count);

        Console.WriteLine("Case 2: s == null");
        RunTests(null, count);

        Console.WriteLine("Case 3: s == \"\"");
        RunTests("", count);
    }

    static void RunTests(string s, int count)
    {
        var ts = IsNullOrEmpty(s, count);
        Console.WriteLine("\tIsNullOrEmpty:         {0}", ts);

        ts = TestLengthZero(s, count);
        Console.WriteLine("\tTest if s.Length == 0: {0}", ts);

        ts = TestEqualsEmpty(s, count);
        Console.WriteLine("\tTest if s == \"\":       {0}", ts);
    }

    static TimeSpan IsNullOrEmpty(string s, int count)
    {
        var sw = Stopwatch.StartNew();
        for (int i = 0; i < count; i++)
        {
            if (string.IsNullOrEmpty(s))
            {
            }
        }
        sw.Stop();
        return sw.Elapsed;
    }

    static TimeSpan TestLengthZero(string s, int count)
    {
        var sw = Stopwatch.StartNew();
        for (int i = 0; i < count; i++)
        {
            if (s == null || s.Length == 0)
            {
            }
        }
        sw.Stop();
        return sw.Elapsed;
    }

    static TimeSpan TestEqualsEmpty(string s, int count)
    {
        var sw = Stopwatch.StartNew();
        for (int i = 0; i < count; i++)
        {
            if (s == null || s == "")
            {
            }
        }
        sw.Stop();
        return sw.Elapsed;
    }
}

以下是结果:

Case 1: s == "test"
        IsNullOrEmpty:         00:00:00.6000748
        Test if s.Length == 0: 00:00:00.5566793
        Test if s == "":       00:00:02.2284007
Case 2: s == null
        IsNullOrEmpty:         00:00:00.5556170
        Test if s.Length == 0: 00:00:00.5569102
        Test if s == "":       00:00:00.5554338
Case 3: s == ""
        IsNullOrEmpty:         00:00:00.5568344
        Test if s.Length == 0: 00:00:00.5556285
        Test if s == "":       00:00:03.0626445

(在启用优化的情况下编译;这些是32位CLR的结果,但64位CLR的结果相似)

正如您所看到的,如果字符串不为null,则调用IsNullOrEmpty比与null""相比要快得多,几乎与{{1}相比快测试长度是否为0.如果字符串为null,则所有3种方法都具有相同的性能。

所以,这样做:

null

可能更慢,而不是更快,而不是:

if(myString != null && myString != "")

你可以这样做:

if(string.IsNullOrEmpty(myString))

但与调用if(myString != null && myString.Length > 0) 相比,性能提升非常小,这会损害可读性。

请注意,此基准测试以1,000,000,000(10亿)次迭代运行;这是必要的,以注意到实际的差异。在现实世界的情景中,差异可能是小的注意;这显然是一种微观优化。

答案 2 :(得分:5)

我会说,即使IsNullOrEmpty有点慢,也可以使用它,因为它比使用奇怪的IF条件更容易混淆和更具可读性。

参见以下示例

if((!string.IsNullOrEmpty(str1)) && (!string.IsNullOrEmpty(str2)) && (!string.IsNullOrEmpty(str3)))
{
//Code here
}

更具可读性
if(str1 != null && str1 != "" && str2 != null && str2 != "" && str3 != null && str3 != "")
{
// Code here
}

答案 3 :(得分:4)

您当前的代码很好,您不应该有任何性能差异。

目前实施方式为:

 public static bool IsNullOrEmpty(String value) 
 {
     return (value == null || value.Length == 0);
 }

Source code take from HERE

如果性能会有差异,那么它必须可以忽略不计。您应该始终考虑对这些情况更具可读性的代码。

您可能还会看到:Premature-Optimization and Performance Anxiety

答案 4 :(得分:1)

如果您在执行时查找响应时间,可以在http://www.dotnetperls.com/isnullorempty上看到“替代方案”部分。

我也认为,IsNullOrEmpty方法比其他方式更清晰。

答案 5 :(得分:1)

http://blogs.msdn.com/b/ericgu/archive/2004/01/29/64717.aspx - 这描述了CLR功能是自动内联的。仅仅因为你今天对它进行了剖析并看到差异并不意味着它在下次运行它时会是相同的。如果您真的关心性能,则可以避免潜在的函数调用,因为您已明确地手动编写它。实际上,保存这样的微观优化,直到你对它进行分析并看到你有需要。

.Net的未来版本也可以将IsNullOrEmpty()的实现更改为优化的本机代码调用。

答案 6 :(得分:0)

调用函数时,会使用额外的汇编指令将另一个堆栈帧放在调用堆栈上。一种优化方法是删除所有这些冗余调用,并用内联代码替换它们(就像“某人”推荐的那样)。但是,这个级别的优化几乎不需要。

只有一次通话,这种速度差异基本上是不可测量的。与您的可读代码一样,可读代码应始终重视不必要的优化。