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

发布于 2024-07-09 03:34:55 字数 274 浏览 6 评论 0原文

哪个更快? 这个:

bool isEqual = (MyObject1 is MyObject2)

或者这个:

bool isEqual = ("blah" == "blah1")

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

Which is faster? This:

bool isEqual = (MyObject1 is MyObject2)

Or this:

bool isEqual = ("blah" == "blah1")

It would be helpful to figure out which one is faster. Obviously, if you apply .ToUpper() to each side of the string comparison like programmers often do, that would require reallocating memory which affects performance. But how about if .ToUpper() is out of the equation like in the above sample?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

初见你 2024-07-16 03:34:56

第一个用于比较类型而不是值。
如果您想将字符串与不区分大小写进行比较,可以使用:

string toto = "toto";
string tata = "tata";

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

Console.WriteLine(isEqual);     

The first one is used to compare types not values.
If you want to compare strings with a non-sensitive case you can use:

string toto = "toto";
string tata = "tata";

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

Console.WriteLine(isEqual);     
南街女流氓 2024-07-16 03:34:56

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

Comparing strings with a "==" operator compares the contents of the string vs. the string object reference. Comparing objects will call the "Equals" method of the object to determine whether they are equal or not. The default implementation of Equals is to do a reference comparison, returning True if both object references are the same physical object. This will likely be faster than the string comparison, but is dependent on the type of object being compared.

廻憶裏菂餘溫 2024-07-16 03:34:56

我假设比较第一个示例中的对象将尽可能快,因为它只是检查两个对象是否指向内存中的同一地址。

正如已经多次提到的,也可以比较字符串上的地址,但如果两个字符串是从不同的源分配的,则这不一定有效。

最后,尽可能尝试根据类型比较对象通常是一种很好的形式。 它通常是最具体的识别方法。 如果您的对象需要用内存中地址以外的其他内容来表示,则可以使用其他属性作为标识符。

I'd assume that comparing the objects in your first example is going to be about as fast as it gets since its simply checking if both objects point to the same address in memory.

As it has been mentioned several times already, it is possible to compare addresses on strings as well, but this won't necessarily work if the two strings are allocated from different sources.

Lastly, its usually good form to try and compare objects based on type whenever possible. Its typically the most concrete method of identification. If your objects need to be represented by something other than their address in memory, its possible to use other attributes as identifiers.

陌生 2024-07-16 03:34:56

如果我理解这个问题,并且您确实想要将引用相等性与普通的旧式“比较内容”进行比较:构建一个测试用例并调用 object.ReferenceEquals 与 a == b 进行比较。

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

If I understand the question and you really want to compare reference equality with the plain old "compare the contents": Build a testcase and call object.ReferenceEquals compared against a == b.

Note: You have to understand what the difference is and that you probably cannot use a reference comparison in most scenarios. If you are sure that this is what you want it might be a tiny bit faster. You have to try it yourself and evaluate if this is worth the trouble at all..

羞稚 2024-07-16 03:34:56

我觉得这些答案都没有解决实际问题。 假设本例中的字符串是类型的名称,我们试图看看比较类型名称或类型来确定它是什么是否更快。

我将其放在一起,令我惊讶的是,检查类型名称字符串比我运行的每次测试中的类型快大约 10%。 我故意将最简单的字符串和类投入使用,看看是否可以更快,结果证明这是可能的。 不确定来自大量继承的类的更复杂的字符串和类型比较。 这当然是一个微操作,我认为在语言发展的某个时刻可能会发生变化。

就我而言,我正在考虑一个基于此名称进行切换的值转换器,但它也可以切换类型,因为每种类型都指定一个唯一的类型名称。 值转换器将根据所呈现的项目类型计算出要显示的字体真棒图标。

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

I don't feel like any of these answers address the actual question. Let's say the string in this example is the type's name and we're trying to see if it's faster to compare a type name or the type to determine what it is.

I put this together and to my surprise, it's about 10% faster to check the type name string than the type in every test I ran. I intentionally put the simplest strings and classes into play to see if it was possible to be faster, and turns out it is possible. Not sure about more complicated strings and type comparisons from heavily inherited classes. This is of course a micro-op and may possibly change at some point in the evolution of the language I suppose.

In my case, I was considering a value converter that switches based on this name, but it could also switch over the type since each type specifies a unique type name. The value converter would figure out the font awesome icon to show based on the type of item presented.

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);
        }
    }
}
背叛残局 2024-07-16 03:34:55

我在这里有点困惑。

正如其他答案所指出的,您正在比较苹果和橙子。 ::rimshot::

如果要确定对象是否属于某种类型,请使用 is 运算符。

如果您想比较字符串,请使用 == 运算符(如果您需要诸如不区分大小写的比较之类的奇特功能,则可以使用其他适当的比较方法)。

一个操作与另一个操作相比有多快(没有双关语)似乎并不重要。


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

如果是这样的话,那么答案是引用比较永远不会比任何其他字符串比较慢。 .NET 中的引用比较与 C 中的指针比较非常相似 - 速度尽可能快。

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

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

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

I'm a little confused here.

As other answers have noted, you're comparing apples and oranges. ::rimshot::

If you want to determine if an object is of a certain type use the is operator.

If you want to compare strings use the == operator (or other appropriate comparison method if you need something fancy like case-insensitive comparisons).

How fast one operation is compared to the other (no pun intended) doesn't seem to really matter.


After closer reading, I think that you want to compare the speed of string comparisions with the speed of reference comparisons (the type of comparison used in the System.Object base type).

If that's the case, then the answer is that reference comparisons will never be slower than any other string comparison. Reference comparison in .NET is pretty much analogous to comparing pointers in C - about as fast as you can get.

However, how would you feel if a string variable s had the value "I'm a string", but the following comparison failed:

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

If you simply compared references, that might happen depending on how the value of s was created. If it ended up not being interned, it would not have the same reference as the literal string, so the comparison would fail. So you might have a faster comparison that didn't always work. That seems to be a bad optimization.

霞映澄塘 2024-07-16 03:34:55

根据《Maximizing .NET Performance》一书
该调用

bool isEqual = String.Equals("test", "test");

的性能与理论上相同,

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

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

调用比调用静态 String.Equals 方法慢,但我认为您需要比较几百万个字符串才能实际检测速度差异。

我给你的建议是这样的; 不必担心哪种字符串比较方法更慢或更快。 在正常的应用程序中,您永远不会注意到其中的差异。 您应该使用您认为最具可读性的方式。

According to the book Maximizing .NET Performance
the call

bool isEqual = String.Equals("test", "test");

is identical in performance to

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

The call

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

is theoretically slower than the call to the static String.Equals method, but I think you'll need to compare several million strings in order to actually detect a speed difference.

My tip to you is this; don't worry about which string comparison method is slower or faster. In a normal application you'll never ever notice the difference. You should use the way which you think is most readable.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文