簡體   English   中英

c# 性能:類型比較與字符串比較

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

哪個更快? 這個:

bool isEqual = (MyObject1 is MyObject2)

或這個:

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

找出哪個更快會很有幫助。 顯然,如果像程序員經常做的那樣將 .ToUpper() 應用於字符串比較的每一側,那將需要重新分配內存,這會影響性能。 但是,如果 .ToUpper() 不在上面示例中的等式之外呢?

我在這里有點困惑。

正如其他答案所指出的那樣,您正在比較蘋果和橙子。 ::rimshot::

如果要確定對象是否屬於某種類型,請使用is運算符。

如果您想比較字符串,請使用==運算符(或其他適當的比較方法,如果您需要一些花哨的東西,例如不區分大小寫的比較)。

一種操作與另一種操作相比有多快(沒有雙關語)似乎並不重要。


仔細閱讀后,我認為您想將字符串比較的速度與引用比較的速度(System.Object 基類型中使用的比較類型)進行比較。

如果是這樣,那么答案是引用比較永遠不會比任何其他字符串比較慢。 .NET 中的引用比較與 C 中的指針比較非常相似 - 盡可能快。

但是,如果字符串變量s的值為"I'm a string" ,但以下比較失敗,您會有什么感覺:

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

如果您只是比較引用,則可能會發生這種情況,具體取決於s的值是如何創建的。 如果它最終沒有被實習,它將與文字字符串具有不同的引用,因此比較將失敗。 所以你可能有一個更快的比較,但並不總是有效。 這似乎是一個糟糕的優化。

根據Maximizing .NET Performance一書,調用

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

在性能上與

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

電話

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

理論上比調用靜態 String.Equals 方法慢,但我認為您需要比較幾百萬個字符串才能實際檢測速度差異。

我給你的提示是這樣的; 不要擔心哪種字符串比較方法更慢或更快。 在正常的應用程序中,您永遠不會注意到差異。 你應該使用你認為最易讀的方式。

第一個用於比較類型而不是值。 如果要將字符串與不敏感的大小寫進行比較,可以使用:

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

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

Console.WriteLine(isEqual);     

如果我理解這個問題,並且您真的想將引用相等性與普通的“比較內容”進行比較:構建一個測試用例並調用object.ReferenceEquals與 a == b 進行比較。

注意:您必須了解區別是什么,並且在大多數情況下您可能無法使用參考比較。 如果您確定這是您想要的,它可能會快一點。 您必須自己嘗試並評估這是否值得麻煩。

你告訴我怎么樣? :)

這篇 Coding Horror post 中獲取代碼,並插入您的代碼來代替他的算法進行測試。

使用“==”運算符比較字符串是將字符串的內容與字符串對象引用進行比較 比較對象會調用對象的“Equals”方法來判斷它們是否相等。 Equals 的默認實現是進行引用比較,如果兩個對象引用是同一個物理對象,則返回 True。 這可能比字符串比較快,但取決於被比較的對象類型。

我覺得這些答案中的任何一個都沒有解決實際問題。 假設此示例中的字符串是類型的名稱,我們正在嘗試查看比較類型名稱或類型以確定它是什么是否更快。

我把它們放在一起,令我驚訝的是,在我運行的每個測試中,檢查類型名稱字符串比檢查類型快 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);
        }
    }
}

我假設比較第一個示例中的對象將盡可能快,因為它只是檢查兩個對象是否指向內存中的相同地址。

正如已經多次提到的那樣,也可以比較字符串上的地址,但如果兩個字符串是從不同來源分配的,則這不一定有效。

最后,在可能的情況下,嘗試根據類型比較對象通常是一種很好的形式。 它通常是最具體的識別方法。 如果您的對象需要用它們在內存中的地址以外的其他東西來表示,則可以使用其他屬性作為標識符。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM