Gibt es einen C # Groß- / Kleinschreibung ohne Berücksichtigung des Operators?

156

Ich weiß, dass bei Folgendem zwischen Groß- und Kleinschreibung unterschieden wird:

if (StringA == StringB) {

Gibt es also einen Operator, der zwei Zeichenfolgen unempfindlich vergleicht?

GateKiller
quelle
mögliches Duplikat von Caselessly Vergleich von Strings in C #
nawfal
Falls jemand über diese Frage stolpert und nach einem Vergleich ohne Berücksichtigung der Groß- und Kleinschreibung für ein Wörterbuch <string, int> sucht, sehen Sie sich diese Frage hier an: Zugriff ohne
Berücksichtigung der
Es wäre wirklich schön; Sagen wir, um eine entsprechende ~=Parallele ==als eine Version zu definieren , bei der die Groß- und Kleinschreibung nicht berücksichtigt wird.
Eidylon
Wenn Microsoft-Entwickler dies sehen, ist in der nächsten Version von csharp meines Erachtens ein Operator erforderlich, bei dem die Groß- und Kleinschreibung nicht berücksichtigt wird. Diese Zeichenfolge.Equal () ist lang.
Rez.Net

Antworten:

288

Versuche dies:

string.Equals(a, b, StringComparison.CurrentCultureIgnoreCase);
John Feminella
quelle
Ich bin ein relativer StackOverflow-Neuling. Können Sie erklären, was Sie mit einem Link meinen? Meinen Sie zu den MSDN-Dokumenten?
John Feminella
55
Wenn Sie einen kultursensitiven Vergleich wünschen, verwenden Sie diese Methode. Wenn Sie nur sicherstellen möchten, dass sowohl "DATEI" als auch "Datei" akzeptiert werden, verwenden Sie "OrdinalIgnoreCase", oder Ihr Code funktioniert möglicherweise nicht an Orten wie türkischen Gebietsschemas. Weitere Informationen finden Sie unter moserware.com/2008/02/does-your-code-pass-turkey-test.html
Jeff Moser
10
Ich bin mir nicht sicher, wovon Samuel spricht ... diese Antwort ist perfekt. Es ist korrekt und selbsterklärend. Es braucht keine Referenzen. +1
Segeln Judo
3
Argh das ist so ein schrecklicher Schluck! Meine Tastatur wird abgenutzt sein. Vorbei sind die Zeiten, in denen ich " if A$=B$ then goto 10"
Sanjay Manohar
9
@ Sanjay Manohar Dann schreibe einen benutzerdefinierten Operator - und ich würde eine bessere Tastatur empfehlen.
Rushyo
37

Der beste Weg , um zwei Zeichenfolgen zu vergleichen, wobei die Groß- und Kleinschreibung der Buchstaben ignoriert wird, ist die statische Methode String.Equals , mit der ein Vergleich der Zeichenfolgen für die Groß- und Kleinschreibung angegeben wird. Dies ist auch der schnellste Weg, viel schneller als die Zeichenfolgen in Klein- oder Großbuchstaben umzuwandeln und danach zu vergleichen.

Ich habe die Leistung beider Ansätze getestet und der Vergleich der ordinalen Ignorierfallzeichenfolgen war mehr als neunmal schneller ! Es ist auch zuverlässiger als das Konvertieren von Zeichenfolgen in Klein- oder Großbuchstaben (siehe das türkische i-Problem). Verwenden Sie daher immer die String.Equals- Methode, um Zeichenfolgen auf Gleichheit zu vergleichen:

String.Equals(string1, string2, StringComparison.OrdinalIgnoreCase);

Wenn Sie einen kulturspezifischen Zeichenfolgenvergleich durchführen möchten, können Sie den folgenden Code verwenden:

String.Equals(string1, string2, StringComparison.CurrentCultureIgnoreCase);

Bitte beachten Sie, dass im zweiten Beispiel die Zeichenfolgenvergleichslogik der aktuellen Kultur verwendet wird, wodurch sie langsamer ist als der Vergleich "Ordinaler Ignorierfall" im ersten Beispiel. Wenn Sie also keine kulturspezifische Zeichenfolgenvergleichslogik benötigen und dies auch sind Verwenden Sie nach maximaler Leistung den Vergleich "Ordinaler Ignorierfall".

Weitere Informationen finden Sie in meinem Blog .

Pavel Vladov
quelle
1
Schlagen Sie nicht vor ToLoweroder ToLowerInvariant: Sie erstellen Speicher, nur um einen Vergleich durchzuführen, und sie können fehlschlagen, wenn neue Zeichensätze zu Unicode hinzugefügt werden. ToUpperscheitert unter anderem am türkischen 'i'; Es gibt keinen Grund, warum ToLowerwir in Zukunft aus ähnlichen Gründen nicht scheitern werden.
Antiduh
@antiduh, danke für deinen Kommentar. Die meisten von uns sind sich dieser potenziellen Probleme bewusst. Viele Tutorials über das Internet geben das türkische "i" als Beispiel. Wie Sie in meinem Beitrag sehen, empfehle ich nicht die Verwendung von ToLoweroder ToLowerInvariantMethoden, ich wollte nur zeigen, wie viel effizienter die String.EqualsMethode ist.
Pavel Vladov
3
"Die meisten von uns sind sich dieser potenziellen Probleme bewusst, viele Tutorials über das Internet geben das türkische 'i' als Beispiel" - nicht genug Leute, und Sie erwähnen es immer noch als zweiten Satz in Ihrer Antwort. Darüber hinaus enthält Ihre Antwort nicht genügend Begründungen, um sie niemals zu verwenden - Sie erwähnen lediglich die Leistung; Leistung ist nicht immer die oberste Priorität. Infolgedessen verstoßen Sie derzeit gegen die Richtlinien des Hilfezentrums. Links zu externen Websites sind in Ordnung, aber Sie haben den Inhalt nicht ausreichend zusammengefasst (türkisches 'i'-Problem). SO ist nicht Ihre Werbeplattform.
Antiduh
20

Es gibt eine Reihe von Eigenschaften für die StringComparerstatische Klasse, die Vergleicher für jede Art von Groß- und Kleinschreibung zurückgeben, die Sie möglicherweise wünschen:

StringComparer Eigenschaften

Zum Beispiel können Sie anrufen

StringComparer.CurrentCultureIgnoreCase.Equals(string1, string2)

oder

StringComparer.CurrentCultureIgnoreCase.Compare(string1, string2)

Es ist ein bisschen sauberer als die string.Equalsoder string.CompareÜberladungen, die ein StringComparisonArgument erfordern.

Ryan Lundy
quelle
15
System.Collections.CaseInsensitiveComparer

oder

System.StringComparer.OrdinalIgnoreCase
Leppie
quelle
Betrifft dies die gesamte Anwendung?
GateKiller
3
Wo finde ich mehr Infos dazu. Bedeutet dies, dass ich == für eine Übereinstimmung verwenden kann, bei der die Groß- und Kleinschreibung nicht berücksichtigt wird?
GateKiller
9
string.Equals(StringA, StringB, StringComparison.CurrentCultureIgnoreCase);
Erick
quelle
8

oder

if (StringA.Equals(StringB, StringComparison.CurrentCultureIgnoreCase)) {

Sie müssen jedoch sicherstellen, dass StringA nicht null ist. Also wahrscheinlich besser für:

string.Equals(StringA , StringB, StringComparison.CurrentCultureIgnoreCase);

wie John vorschlug

BEARBEITEN: Fehler behoben

Grzenio
quelle
4

Sie können verwenden

if (stringA.equals(StringB, StringComparison.CurrentCultureIgnoreCase))
Andy Mikula
quelle
3

Operator? NEIN, aber ich denke, Sie können Ihre Kultur ändern, sodass beim Vergleich von Zeichenfolgen nicht zwischen Groß- und Kleinschreibung unterschieden wird.

// you'll want to change this...
System.Threading.Thread.CurrentThread.CurrentCulture
// and you'll want to custimize this
System.Globalization.CultureInfo.CompareInfo

Ich bin zuversichtlich, dass sich dadurch die Art und Weise ändern wird, in der Zeichenfolgen vom Gleichheitsoperator verglichen werden.

John Leidegren
quelle
Ja, um es gelinde auszudrücken, es ist absolut nicht das, was Sie tun möchten, es sei denn, Sie möchten, dass bei allen Zeichenfolgenvergleichen die Groß- und Kleinschreibung nicht berücksichtigt wird. Aber ich denke, es ändert das Verhalten des Gleichheitsoperators.
John Leidegren
3

Hier eine Idee zur Vereinfachung der Syntax:

public class IgnoreCase
{
    private readonly string _value;

    public IgnoreCase(string s)
    {
        _value = s;
    }

    protected bool Equals(IgnoreCase other)
    {
        return this == other;
    }

    public override bool Equals(object obj)
    {
        return obj != null &&
               (ReferenceEquals(this, obj) || (obj.GetType() == GetType() && this == (IgnoreCase) obj));
    }

    public override int GetHashCode()
    {
        return _value?.GetHashCode() ?? 0;
    }

    public static bool operator ==(IgnoreCase a, IgnoreCase b)
    {
        return string.Equals(a, b, StringComparison.OrdinalIgnoreCase);
    }

    public static bool operator !=(IgnoreCase a, IgnoreCase b)
    {
        return !(a == b);
    }

    public static implicit operator string(IgnoreCase s)
    {
        return s._value;
    }

    public static implicit operator IgnoreCase(string s)
    {
        return new IgnoreCase(s);
    }
}

Verwendbar wie:

Console.WriteLine((IgnoreCase) "a" == "b"); // false
Console.WriteLine((IgnoreCase) "abc" == "abC"); // true
Console.WriteLine((IgnoreCase) "Abc" == "aBc"); // true
Console.WriteLine((IgnoreCase) "ABC" == "ABC"); // true
renouve
quelle
Obwohl mir die sauber aussehende Verwendungssyntax gefällt , ist sie etwas irreführend ( IgnoreCasevs IgnoreCaseString) und mehrdeutig (Java wählt implizites Unboxing vs. implizites Boxen aus, daher glaube ich, dass dies in Java mit der impliziten Umwandlung in einen String nicht funktionieren würde). Dadurch entsteht der Speicheraufwand für zwei neue Objekte, wobei die Aufrufbaumausführung für jeden Vergleich in mehrere verschachtelte Methodenaufrufe für den angezeigten Anwendungsfall springt. In den meisten Fällen ist die Leistung jedoch wahrscheinlich gut genug.
Arkaine55
Dies ist zwar eine clevere Idee, aus Sicht der Wartbarkeit jedoch nicht wirklich sinnvoll. Sie erstellen effektiv einen Ersatzzeichenfolgentyp, anstatt den im System integrierten Zeichenfolgentyp zu verwenden. Der Programmierer, der danach kommt, wird auf einen Blick nicht verstehen, was los ist, und dann wird er / sie Sie beschimpfen. Die Verwendung von string.Equals () ist gar nicht so schlecht und die meisten Leute werden verstehen, was es tut.
ntcolonel
1

Ich bin es gewohnt, am Ende dieser Vergleichsmethoden zu tippen: , StringComparison.

Also habe ich eine Erweiterung gemacht.

namespace System
{   public static class StringExtension
    {
        public static bool Equals(this string thisString, string compareString,
             StringComparison stringComparison)
        {
            return string.Equals(thisString, compareString, stringComparison);
        }
    }
}

Beachten Sie nur, dass Sie thisStringvor dem Aufruf von ext auf null prüfen müssen .

Valamas
quelle
1
Entspricht dies dieser integrierten Methode in aktuellen .NET Framework-Versionen? docs.microsoft.com/en-gb/dotnet/api/…
Bernard Vander Beken
1
Erscheint so. Es sieht so aus, als ob die späteren Versionen von .net dies jetzt enthalten.
Valamas
Verfügbar seit .NET 4.5 und allen .NET Core-Versionen.
Bernard Vander Beken
0
string.Compare(string1, string2, true)
user25623
quelle
0
if (StringA.ToUpperInvariant() == StringB.ToUpperInvariant()) {

Leute berichten, dass ToUpperInvariant () schneller ist als ToLowerInvariant ().

Knoopx
quelle
1
Invariante kann eine schlechte Idee sein, wenn die aktuelle oder gewünschte Kultur spezielle Regeln für das obere Gehäuse hat.
OregonGhost
Erstellt dies eine neue Kopie jeder Zeichenfolge? Wenn ja, schlechte Idee.
cjk
1
Dies löst auch eine Ausnahme aus, wenn eine (oder beide) Zeichenfolgen null sind.
Tvanfosson
3
In Bezug auf die Leistung ist dies keine so gute Lösung, da Sie auch hier zwei neue Zeichenfolgeninstanzen erstellen.
Frederik Gheysels
0

Andere Antworten sind hier völlig gültig, aber irgendwie dauert es einige Zeit, sie zu tippen StringComparison.OrdinalIgnoreCaseund auch zu verwenden String.Compare.

Ich habe eine einfache String-Erweiterungsmethode codiert, bei der Sie angeben können, ob beim Vergleich zwischen Groß- und Kleinschreibung oder Boolescher Wert zwischen Groß- und Kleinschreibung unterschieden wird - siehe folgende Antwort:

https://stackoverflow.com/a/49208128/2338477

TarmoPikaro
quelle