Frage

Der Vergleich von Zeichenfolgen in C# ist ziemlich einfach.Tatsächlich gibt es mehrere Möglichkeiten, dies zu tun.Einige habe ich im folgenden Block aufgelistet.Was mich interessiert, sind die Unterschiede zwischen ihnen und wann man sie den anderen vorziehen sollte?Sollte man es unbedingt meiden?Gibt es noch mehr, die ich nicht aufgelistet habe?

string testString = "Test";
string anotherString = "Another";

if (testString.CompareTo(anotherString) == 0) {}
if (testString.Equals(anotherString)) {}
if (testString == anotherString) {}

(Notiz:Ich suche in diesem Beispiel nach Gleichheit, nicht kleiner oder größer als, aber Sie können dies auch gerne kommentieren)

War es hilfreich?

Lösung

Hier sind die Regeln für die Funktionsweise dieser Funktionen:

stringValue.CompareTo(otherStringValue)

  1. null kommt vor einer Zeichenfolge
  2. es benutzt CultureInfo.CurrentCulture.CompareInfo.Compare, was bedeutet, dass ein kulturabhängiger Vergleich verwendet wird.Das könnte das bedeuten ß wird gleich vergleichen SS in Deutschland oder ähnlich

stringValue.Equals(otherStringValue)

  1. null wird mit nichts gleichgesetzt
  2. es sei denn, Sie geben a an StringComparison Option wird etwas verwendet, das wie eine direkte ordinale Gleichheitsprüfung aussieht, d. h. ß ist nicht dasselbe wie SS, in jeder Sprache oder Kultur

stringValue == otherStringValue

  1. Ist nicht dasselbe wie stringValue.Equals().
  2. Der == Der Operator ruft die Statik auf Equals(string a, string b) Methode (die wiederum an eine interne geht EqualsHelper um den Vergleich durchzuführen.
  3. Berufung .Equals() auf einen null Zeichenfolge erhält null Referenzausnahme, solange aktiviert == nicht.

Object.ReferenceEquals(stringValue, otherStringValue)

Überprüft nur, ob die Referenzen gleich sind, d. h.Es handelt sich nicht nur um zwei Strings mit demselben Inhalt, Sie vergleichen ein String-Objekt mit sich selbst.


Beachten Sie, dass es bei den oben genannten Optionen, die Methodenaufrufe verwenden, Überladungen mit mehr Optionen gibt, um anzugeben, wie verglichen werden soll.

Mein Rat, wenn Sie nur die Gleichheit prüfen möchten, ist, sich zu entscheiden, ob Sie einen kulturabhängigen Vergleich verwenden möchten oder nicht, und ihn dann zu verwenden .CompareTo oder .Equals, je nach Wahl.

Andere Tipps

Von MSDN:

"Die Vergleichsmethode wurde hauptsächlich zur Verwendung bei Sortier- oder Alphabetisierungsvorgängen entwickelt.Es sollte nicht verwendet werden, wenn der Hauptzweck des Methodenaufrufs besteht, festzustellen, ob zwei Zeichenfolgen gleichwertig sind.Um festzustellen, ob zwei Zeichenfolgen gleichwertig sind, rufen Sie die Equals -Methode auf. "

Sie schlagen die Verwendung vor .Equals anstatt .CompareTo wenn es nur um Gleichberechtigung geht.Ich bin mir nicht sicher, ob es da einen Unterschied gibt .Equals Und == für die string Klasse.Ich werde manchmal verwenden .Equals oder Object.ReferenceEquals anstatt == für meine eigenen Klassen, falls zu einem späteren Zeitpunkt jemand vorbeikommt und das neu definiert == Operator für diese Klasse.

Wenn Sie jemals neugierig auf die Unterschiede in den BCL-Methoden sind, Reflektor ist dein Freund :-)

Ich folge diesen Richtlinien:

Genaue Übereinstimmung: BEARBEITEN:Bisher habe ich den ==-Operator immer nach dem Prinzip verwendet, dass innerhalb von Equals(string, string) der Objekt-==-Operator zum Vergleichen der Objektreferenzen verwendet wird, aber es scheint, dass strA.Equals(strB) insgesamt immer noch 1-11 % schneller ist als string. Equals(strA, strB), strA == strB und string.CompareOrdinal(strA, strB).Ich habe mit einer Stoppuhr einen Schleifentest für sowohl interne als auch nicht interne Zeichenfolgenwerte mit gleichen/unterschiedlichen Zeichenfolgenlängen und unterschiedlichen Größen (1B bis 5 MB) durchgeführt.

strA.Equals(strB)

Für Menschen lesbare Übereinstimmung (westliche Kulturen, ohne Berücksichtigung der Groß-/Kleinschreibung):

string.Compare(strA, strB, StringComparison.OrdinalIgnoreCase) == 0

Für Menschen lesbare Übereinstimmung (alle anderen Kulturen, ohne Berücksichtigung von Groß-/Kleinschreibung/Akzent/Kana/usw., definiert durch CultureInfo):

string.Compare(strA, strB, myCultureInfo) == 0

Für Menschen lesbarer Abgleich mit benutzerdefinierten Regeln (alle anderen Kulturen):

CompareOptions compareOptions = CompareOptions.IgnoreCase
                              | CompareOptions.IgnoreWidth
                              | CompareOptions.IgnoreNonSpace;
string.Compare(strA, strB, CultureInfo.CurrentCulture, compareOptions) == 0

Als Ed gesagt, CompareTo wird zum Sortieren verwendet.

Es gibt jedoch einen Unterschied zwischen .Equals und ==.

== löst sich auf im Wesentlichen der folgende Code:

if(object.ReferenceEquals(left, null) && 
   object.ReferenceEquals(right, null))
    return true;
if(object.ReferenceEquals(left, null))
    return right.Equals(left);
return left.Equals(right);

Der einfache Grund ist, dass Folgendes eine Ausnahme auslöst:

string a = null;
string b = "foo";

bool equal = a.Equals(b);

Und das Folgende wird nicht:

string a = null;
string b = "foo";

bool equal = a == b;

Gute Erklärungen und Vorgehensweisen zu Problemen beim String-Vergleich finden Sie im Artikel Neue Empfehlungen für die Verwendung von Strings in Microsoft .NET 2.0 und auch in Best Practices für die Verwendung von Strings im .NET Framework.


Jede der genannten Methoden (und andere) hat einen bestimmten Zweck.Der Hauptunterschied zwischen ihnen besteht darin, welche Art von StringComparison-Enumeration Sie verwenden standardmäßig.Es gibt mehrere Möglichkeiten:

  • AktuelleKultur
  • CurrentCultureIgnoreCase
  • InvarianteKultur
  • InvariantCultureIgnoreCase
  • Ordinal
  • OrdinalIgnoreCase

Jeder der oben genannten Vergleichstypen zielt auf einen anderen Anwendungsfall ab:

  • Ordinal
    • Bei internen Bezeichnern muss die Groß-/Kleinschreibung beachtet werden
    • Bezeichner, bei denen die Groß-/Kleinschreibung beachtet wird, in Standards wie XML und HTTP
    • Bei sicherheitsrelevanten Einstellungen muss die Groß-/Kleinschreibung beachtet werden
  • OrdinalIgnoreCase
    • Interne Bezeichner, bei denen die Groß-/Kleinschreibung nicht beachtet wird
    • Bezeichner ohne Berücksichtigung der Groß-/Kleinschreibung in Standards wie XML und HTTP
    • Dateipfade (unter Microsoft Windows)
    • Registrierungsschlüssel/-werte
    • Umgebungsvariablen
    • Ressourcenbezeichner (z. B. Handle-Namen)
    • Sicherheitsbezogene Einstellungen ohne Berücksichtigung der Groß- und Kleinschreibung
  • InvariantCulture oder InvariantCultureIgnoreCase
    • Einige blieben sprachlich relevante Daten bestehen
    • Anzeige sprachlicher Daten, die eine feste Sortierreihenfolge erfordern
  • CurrentCulture oder CurrentCultureIgnoreCase
    • Dem Benutzer angezeigte Daten
    • Die meisten Benutzereingaben

Beachten Sie, dass StringComparison-Enumeration sowie Überladungen für String-Vergleichsmethoden gibt es seit .NET 2.0.


String.CompareTo-Methode (String)

Ist tatsächlich eine typsichere Implementierung von IComparable.CompareTo-Methode.Standardinterpretation:AktuelleKultur.

Verwendung:

Die CompareTo-Methode wurde hauptsächlich für die Verwendung bei Sortier- oder Alphabetisierungsvorgängen entwickelt

Daher

Bei der Implementierung der IComparable-Schnittstelle wird unbedingt diese Methode verwendet

String.Compare-Methode

Ein statisches Mitglied von String-Klasse das viele Überladungen hat.Standardinterpretation:AktuelleKultur.

Wann immer möglich, sollten Sie eine Überladung der Compare-Methode aufrufen, die einen StringComparison-Parameter enthält.

String.Equals-Methode

Von der Object-Klasse überschrieben und aus Gründen der Typsicherheit überladen.Standardinterpretation:Ordinal.Beachte das:

Zu den Gleichheitsmethoden der String-Klasse gehören die statisch ist gleich, Die statischer Operator ==, und das Instanzmethode Equals.


StringComparer-Klasse

Es gibt auch eine andere Möglichkeit, mit String-Vergleichen umzugehen, die insbesondere auf die Sortierung abzielt:

Du kannst den ... benutzen StringComparer-Klasse um einen typspezifischen Vergleich zu erstellen, um die Elemente in einer generischen Sammlung zu sortieren.Klassen wie Hashtable, Dictionary, SortedList und SortedList verwenden die StringComparer-Klasse für Sortierzwecke.

Nicht, dass die Leistung in 99 % der Fälle, in denen Sie dies tun müssen, normalerweise eine Rolle spielt, aber wenn Sie dies mehrere Millionen Mal in einer Schleife tun müssten, würde ich Ihnen dringend empfehlen, .Equals oder == zu verwenden, denn sobald ein Zeichen gefunden wird Wenn das nicht übereinstimmt, wird das Ganze als falsch ausgegeben, aber wenn Sie CompareTo verwenden, muss es herausfinden, welches Zeichen kleiner als das andere ist, was zu einer etwas schlechteren Leistungszeit führt.

Wenn Ihre App in verschiedenen Ländern ausgeführt wird, empfehle ich Ihnen, einen Blick auf die Auswirkungen von CultureInfo zu werfen und möglicherweise .Equals zu verwenden.Da ich eigentlich nur Apps für die USA schreibe (und es mir egal ist, ob es bei jemandem nicht richtig funktioniert), verwende ich immer einfach ==.

In den von Ihnen hier aufgelisteten Formen gibt es keinen großen Unterschied zwischen den beiden. CompareTo ruft schließlich a an CompareInfo Methode, die einen Vergleich mit der aktuellen Kultur durchführt; Equals wird von aufgerufen == Operator.

Wenn man Überlastungen berücksichtigt, sieht die Sache anders aus. Compare Und == kann nur die aktuelle Kultur zum Vergleichen einer Zeichenfolge verwenden. Equals Und String.Compare kann eine nehmen StringComparison Aufzählungsargument, mit dem Sie Vergleiche ohne Berücksichtigung der Kultur oder Groß-/Kleinschreibung angeben können.Nur String.Compare ermöglicht Ihnen die Angabe eines CultureInfo und Vergleiche mit einer anderen Kultur als der Standardkultur durchführen.

Aufgrund seiner Vielseitigkeit finde ich, dass ich es verwende String.Compare mehr als jede andere Vergleichsmethode;Dadurch kann ich genau angeben, was ich möchte.

Ein GROSSER Unterschied besteht darin, dass .Equals() eine Ausnahme auslöst, wenn die erste Zeichenfolge null ist, während dies bei == nicht der Fall ist.

       string s = null;
        string a = "a";
        //Throws {"Object reference not set to an instance of an object."}
        if (s.Equals(a))
            Console.WriteLine("s is equal to a");
        //no Exception
        if(s==a)
            Console.WriteLine("s is equal to a");
  • s1.CompareTo(s2): NICHT verwenden, wenn der Hauptzweck darin besteht, festzustellen, ob zwei Zeichenfolgen äquivalent sind
  • s1 == s2: Groß-/Kleinschreibung kann nicht ignoriert werden
  • s1.Equals(s2, StringComparison): Löst eine NullReferenceException aus, wenn s1 null ist
  • String.Equals(s2, StringComparison): Durch den Eliminierungsprozess, dies statisch Methode ist die GEWINNER (unter der Annahme eines typischen Anwendungsfalls zur Bestimmung, ob zwei Zeichenfolgen gleichwertig sind)!

Die Verwendung von .Equals ist auch viel einfacher lesen.

Mit .Equals erhalten Sie auch die StringComparison-Optionen.Sehr praktisch, um Groß- und Kleinschreibung und andere Dinge zu ignorieren.

Übrigens wird dies als falsch ausgewertet

string a = "myString";
string b = "myString";

return a==b

Da == die Werte von a und b (die Zeiger sind) vergleicht, wird dies nur dann als wahr ausgewertet, wenn die Zeiger auf dasselbe Objekt im Speicher zeigen..Equals dereferenziert die Zeiger und vergleicht die an den Zeigern gespeicherten Werte.a.Equals(b) wäre hier wahr.

und wenn Sie b ändern zu:

b = "MYSTRING";

dann ist a.Equals(b) falsch, aber

a.Equals(b, StringComparison.OrdinalIgnoreCase) 

wäre wahr

a.CompareTo(b) ruft die CompareTo-Funktion der Zeichenfolge auf, die die Werte an den Zeigern vergleicht und <0 zurückgibt, wenn der bei a gespeicherte Wert kleiner ist als der bei b gespeicherte Wert, 0 zurückgibt, wenn a.Equals(b) wahr ist, und >0 sonst.Hierbei wird jedoch die Groß-/Kleinschreibung beachtet. Ich denke, es gibt möglicherweise Optionen für CompareTo, um die Groß-/Kleinschreibung usw. zu ignorieren, aber ich habe jetzt keine Zeit, nachzuschauen.Wie andere bereits angegeben haben, würde dies zur Sortierung erfolgen.Ein solcher Gleichheitsvergleich würde zu unnötigem Mehraufwand führen.

Ich lasse sicher Dinge weg, aber ich denke, das sollten genug Informationen sein, um mit dem Experimentieren zu beginnen, falls Sie weitere Details benötigen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top