简体   繁体   English

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

[英]c# performance: type comparison vs. string comparison

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.显然,如果像程序员经常做的那样将 .ToUpper() 应用于字符串比较的每一侧,那将需要重新分配内存,这会影响性能。 But how about if .ToUpper() is out of the equation like in the above sample?但是,如果 .ToUpper() 不在上面示例中的等式之外呢?

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.如果要确定对象是否属于某种类型,请使用is运算符。

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).仔细阅读后,我认为您想将字符串比较的速度与引用比较的速度(System.Object 基类型中使用的比较类型)进行比较。

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. .NET 中的引用比较与 C 中的指针比较非常相似 - 尽可能快。

However, how would you feel if a string variable s had the value "I'm a string" , but the following comparison failed:但是,如果字符串变量s的值为"I'm a string" ,但以下比较失败,您会有什么感觉:

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.如果您只是比较引用,则可能会发生这种情况,具体取决于s的值是如何创建的。 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.这似乎是一个糟糕的优化。

According to the book Maximizing .NET Performance the call根据Maximizing .NET Performance一书,调用

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.理论上比调用静态 String.Equals 方法慢,但我认为您需要比较几百万个字符串才能实际检测速度差异。

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.你应该使用你认为最易读的方式。

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

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.如果我理解这个问题,并且您真的想将引用相等性与普通的“比较内容”进行比较:构建一个测试用例并调用object.ReferenceEquals与 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..您必须自己尝试并评估这是否值得麻烦。

How about you tell me?你告诉我怎么样? :) :)

Take the code from this Coding Horror post , and insert your code to test in place of his algorithm.这篇 Coding Horror post 中获取代码,并插入您的代码来代替他的算法进行测试。

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.比较对象会调用对象的“Equals”方法来判断它们是否相等。 The default implementation of Equals is to do a reference comparison, returning True if both object references are the same physical object. Equals 的默认实现是进行引用比较,如果两个对象引用是同一个物理对象,则返回 True。 This will likely be faster than the string comparison, but is dependent on the type of object being compared.这可能比字符串比较快,但取决于被比较的对象类型。

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.我把它们放在一起,令我惊讶的是,在我运行的每个测试中,检查类型名称字符串比检查类型快 10%。 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);
        }
    }
}

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.如果您的对象需要用它们在内存中的地址以外的其他东西来表示,则可以使用其他属性作为标识符。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM