C#性能:类型比较与字符串比较

5
哪个更快?是这个:
bool isEqual = (MyObject1 is MyObject2)

或者这样:
bool isEqual = ("blah" == "blah1")

确定哪个更快会很有帮助。显然,如果像程序员经常做的那样将.ToUpper()应用于字符串比较的每一侧,那将需要重新分配内存,这会影响性能。但是,如果像上面的示例中一样不考虑.ToUpper()呢?

8个回答

11

我有点困惑。

正如其他答案所指出的那样,你在比较不同类型的变量。如果你想判断一个对象是否属于某个特定类型,请使用is 运算符。 如果你想比较字符串,请使用 == 运算符(或其他适当的比较方法,例如大小写不敏感比较等)。 单个操作的速度相对于另一个操作的速度(开玩笑的)似乎并不重要。


经过仔细阅读,我认为您想比较字符串比较的速度与引用比较(System.Object基类型中使用的比较类型)的速度。

如果是这种情况,那么答案是引用比较永远不会比任何其他字符串比较慢。在.NET中进行引用比较就像在C语言中比较指针一样快。

然而,如果一个字符串变量s的值为"I'm a string",但以下比较失败,您会有什么感觉:

if (((object) s) == ((object) "I'm a string")) { ... }

如果你只是比较引用,那取决于s的值是如何创建的,这种情况可能会发生。如果它最终未被内部化,它将不具有与字面字符串相同的引用,因此比较将失败。因此,您可能会得到一个更快的比较,但并不总是有效。这似乎是一种糟糕的优化。


3
其他答案忽略了关键点,即“is”运算符并不像提问者认为的那样起作用。 - Robert Rossney

5
根据《最大化.NET性能》一书所述,该调用
bool isEqual = String.Equals("test", "test");

与...在性能上完全相同

bool isEqual = ("test" == "test");

电话通话
bool isEqual = "test".Equals("test");

在理论上,使用非静态的String.Equals方法比调用静态的String.Equals方法慢,但我认为您需要比较数百万个字符串才能真正检测到速度差异。

我的建议是:不要担心哪种字符串比较方法更慢或更快。在正常应用程序中,您永远不会注意到这种差异。您应该使用最容易阅读的方式。


尼古拉斯·J·温霍尔特是作者吗?您认为这本书值得推荐阅读吗? - JSWork

4
第一个用于比较类型而不是值。 如果您想比较大小写不敏感的字符串,可以使用以下语句:
string toto = "toto";
string tata = "tata";

bool isEqual = string.Compare(toto, tata, StringComparison.InvariantCultureIgnoreCase) == 0;    

Console.WriteLine(isEqual);     

0

如果我理解问题并且你真的想比较引用相等性和普通的“比较内容”:构建一个测试用例并调用object.ReferenceEquals与a == b进行比较。

注意:你必须理解差异,并且在大多数情况下可能无法使用引用比较。如果你确定这就是你想要的,它可能会快一点。你必须自己尝试并评估是否值得麻烦。


0

0

使用“==”运算符比较字符串会比较字符串的内容和字符串对象引用。比较对象将调用对象的“Equals”方法来确定它们是否相等。Equals的默认实现是进行引用比较,如果两个对象引用是相同的物理对象,则返回True。这可能比字符串比较更快,但取决于所比较的对象类型。


0

我认为,在您的第一个示例中比较对象将是最快的,因为它只是检查两个对象是否指向内存中的同一地址。

正如已经多次提到的那样,也可以比较字符串的地址,但如果这两个字符串来自不同的源,则不一定有效。

最后,通常最好根据类型尝试比较对象。这通常是最具体的识别方法。如果您的对象需要用其他属性表示,而不是它们在内存中的地址,则可以使用其他属性作为标识符。


你也错过了 "is" 运算符的含义,是吗? - Benjamin Podszun

0

我觉得这些答案都没有真正回答问题。假设在这个例子中,字符串是类型的名称,我们想知道比较类型名称和类型本身哪个更快。

我进行了测试,令人惊讶的是,在我运行的每个测试中,检查类型名称字符串比检查类型本身要快约10%。我故意使用最简单的字符串和类来测试是否可能更快,结果证明确实可以。不确定对于更复杂的字符串和从大量继承类中比较类型会怎样。当然,这只是微操作,随着语言演变,可能会发生变化。

在我的情况下,我考虑了一个基于此名称切换的值转换器,但它也可以根据类型进行切换,因为每种类型都指定了唯一的类型名称。该值转换器将根据呈现的项目类型确定要显示的字体awesome图标。

using System;
using System.Diagnostics;
using System.Linq;

namespace ConsoleApp1
{
    public sealed class A
    {
        public const string TypeName = "A";
    }

    public sealed class B
    {
        public const string TypeName = "B";
    }

    public sealed class C
    {
        public const string TypeName = "C";
    }

    class Program
    {
        static void Main(string[] args)
        {
            var testlist = Enumerable.Repeat(0, 100).SelectMany(x => new object[] { new A(), new B(), new C() }).ToList();

            int count = 0;

            void checkTypeName()
            {
                foreach (var item in testlist)
                {
                    switch (item)
                    {
                        case A.TypeName:
                            count++;
                            break;
                        case B.TypeName:
                            count++;
                            break;
                        case C.TypeName:
                            count++;
                            break;
                        default:
                            break;
                    }
                }
            }

            void checkType()
            {
                foreach (var item in testlist)
                {
                    switch (item)
                    {
                        case A _:
                            count++;
                            break;
                        case B _:
                            count++;
                            break;
                        case C _:
                            count++;
                            break;
                        default:
                            break;
                    }
                }
            }

            Stopwatch sw = Stopwatch.StartNew();
            for (int i = 0; i < 100000; i++)
            {
                checkTypeName();
            }
            sw.Stop();
            Console.WriteLine(sw.Elapsed);
            sw.Restart();
            for (int i = 0; i < 100000; i++)
            {
                checkType();
            }
            sw.Stop();
            Console.WriteLine(sw.Elapsed);
        }
    }
}

10%的差异接近于统计误差。您能否在运行checkTypeName()之前尝试运行checkType(),并确认性能差异是否仍然存在? - Theodor Zoulias
我用了很多不同的方法,但结果总是一样。在任何配置下进行类型检查都不会更快。 - MPavlak

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接