7

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

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

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

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

我有点困惑。

4

7 回答 7

15

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

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

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

于 2013-08-26T14:48:49.183 回答
9

像其他回答的人一样,我认为不会有性能差异,但为了确定,我运行了一个基准测试。结果和我预想的不太一样……

这是我的基准测试的代码:

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;
    }
}

结果如下:

案例1:s ==“测试”
        IsNullOrEmpty:00:00:00.6000748
        测试 s.Length == 0: 00:00:00.5566793
        测试 s == "": 00:00:02.2284007
案例2:s == null
        IsNullOrEmpty: 00:00:00.5556170
        测试 s.Length == 0: 00:00:00.5569102
        测试 s == "": 00:00:00.5554338
案例 3:s == ""
        IsNullOrEmpty:00:00:00.5568344
        测试 s.Length == 0: 00:00:00.5556285
        测试 s == "": 00:00:03.0626445

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

如您所见,如果字符串不为空,则调用比与IsNullOrEmpty比较快得多,并且几乎与比较和测试长度是否为 0一样快。如果字符串为空,则所有 3 种方法具有相同的性能。null""null

所以,这样做:

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

可能会比这更慢,而不是更快:

if(string.IsNullOrEmpty(myString))

你可以这样做:

if(myString != null && myString.Length > 0)

但是与调用相比,性能提升会非常小IsNullOrEmpty,并且会损害可读性。

请注意,此基准测试运行了 1,000,000,000(10 亿)次迭代;这对于注意到实际差异是必要的。在现实世界的场景中,差异可能很小而无法注意到。这显然是一个微优化。

于 2013-08-26T15:45:31.660 回答
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
}
于 2013-08-26T14:54:33.997 回答
4

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

目前它被实现为:

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

源代码取自这里

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

您可能还会看到:过早优化和性能焦虑

于 2013-08-26T14:51:55.647 回答
1

http://blogs.msdn.com/b/ericgu/archive/2004/01/29/64717.aspx -- This describes has CLR functions are automatically inlined. Just because you profile it today and see a difference does not mean it will be the same the next time you run it. If you are really concerned about performance, you avoid the potential function call as you explicitly inlined it by hand. Really though, save such micro-optimizations till you profile it and see you have a need.

A future version of .Net could also Change the implementation of IsNullOrEmpty() to be an optimized native code call.

于 2013-08-26T14:53:33.950 回答
1

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

我也认为, IsNullOrEmpty 方法方式比其他方式更干净。

于 2013-08-26T14:51:46.617 回答
0

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

这种速度上的差异基本上是单次调用无法测量的。像您的代码一样,可读代码应该始终被重视而不是不必要的优化。

于 2013-08-26T14:55:25.153 回答