Esiste un operatore uguale a maiuscole e minuscole C #?


156

So che quanto segue distingue tra maiuscole e minuscole:

if (StringA == StringB) {

Quindi esiste un operatore che confronterà due stringhe in modo insensibile?



Nel caso in cui qualcuno si imbattesse in questa domanda alla ricerca di un confronto senza distinzione tra maiuscole e minuscole per un dizionario <string, int>, dai un'occhiata a questa domanda qui: Accesso insensibile alle maiuscole per il dizionario generico
Robotnik

Sarebbe davvero bello; diciamo di definire un corrispondente ~=al parallelo ==come una versione senza distinzione tra maiuscole e minuscole.
eidylon,

Se gli sviluppatori Microsoft lo vedono, penso che nella prossima versione di csharp sia necessario un operatore senza distinzione tra maiuscole e minuscole. Questa stringa.Equal () è lunga.
Rez.Net,

Risposte:


288

Prova questo:

string.Equals(a, b, StringComparison.CurrentCultureIgnoreCase);

Sono un principiante StackOverflow relativo - puoi spiegare cosa intendi aggiungendo un link? Intendi i documenti MSDN?
John Feminella,

55
Se si desidera un confronto sensibile alla cultura, utilizzare questo metodo. Se vuoi solo assicurarti che "FILE" e "file" siano entrambi accettati, usa "OrdinalIgnoreCase" o il tuo codice potrebbe non funzionare in luoghi come le impostazioni locali turche. Per maggiori informazioni, consultare moserware.com/2008/02/does-your-code-pass-turkey-test.html
Jeff Moser

10
Non sono sicuro di cosa stia parlando Samuel ... questa risposta è perfetta. È corretto e autoesplicativo. Non ha bisogno di riferimenti. +1
Vela Judo

3
Argh questo è un boccone così terribile! la mia tastiera si consumerà. Sono finiti i giorni in cui posso usare " if A$=B$ then goto 10"
Sanjay Manohar,

9
@Sanjay Manohar Quindi scrivi un operatore personalizzato e consiglierei una tastiera migliore.
Rushyo,

37

Il modo migliore per confrontare 2 stringhe ignorando il caso delle lettere è utilizzare il metodo statico String.Equals che specifica un confronto di stringhe di maiuscole ordinali. Questo è anche il modo più veloce, molto più veloce di convertire le stringhe in lettere minuscole o maiuscole e confrontarle successivamente.

Ho testato le prestazioni di entrambi gli approcci e il confronto tra stringhe di casi ignorate ordinali è stato più di 9 volte più veloce ! È anche più affidabile della conversione di stringhe in lettere minuscole o maiuscole (controlla il problema turco i). Quindi usa sempre il metodo String.Equals per confrontare le stringhe per l'uguaglianza:

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

Se si desidera eseguire un confronto di stringhe specifico della cultura, è possibile utilizzare il seguente codice:

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

Si noti che il secondo esempio utilizza la logica di confronto delle stringhe della cultura corrente, che lo rende più lento rispetto al confronto "ordinale ignora caso" nel primo esempio, quindi se non è necessaria alcuna logica di confronto delle stringhe specifica della cultura e si è dopo il massimo delle prestazioni, utilizzare il confronto "ordinale ignora caso".

Per ulteriori informazioni, leggi la storia completa sul mio blog .


1
Non suggerire ToLowero ToLowerInvariant: creano memoria solo per eseguire un confronto e potrebbero non riuscire poiché nuovi set di caratteri vengono aggiunti a Unicode. ToUpperfallisce a causa della "i" turca, tra le altre; non c'è motivo per cui ToLowernon fallirà in futuro per ragioni simili.
antiduh,

@antiduh, grazie per il tuo commento. La maggior parte di noi è a conoscenza di questi potenziali problemi, molti tutorial su Internet danno l'esempio della "i" turca. Come vedi nel mio post, sconsiglio di utilizzare metodi ToLowero ToLowerInvariantmetodi, volevo solo mostrare quanto sia più efficiente il String.Equalsmetodo.
Pavel Vladov,

3
"La maggior parte di noi è a conoscenza di questi potenziali problemi, molti tutorial su Internet danno l'esempio della" i "turca" - non ci sono abbastanza persone e lo stai ancora citando come seconda frase nella tua risposta. Inoltre, la tua risposta non include una giustificazione sufficiente per non usarla mai: fai semplicemente riferimento alle prestazioni; le prestazioni non sono sempre la massima priorità. Di conseguenza, stai attualmente violando le linee guida del Centro assistenza; i collegamenti a siti esterni vanno bene, ma non hai riepilogato sufficientemente il contenuto (problema "i" turco). SO non è la tua piattaforma pubblicitaria.
antiduh,

20

Esistono numerose proprietà nella StringComparerclasse statica che restituiscono comparatori per qualsiasi tipo di distinzione tra maiuscole e minuscole che potresti desiderare:

StringComparer Proprietà

Ad esempio, puoi chiamare

StringComparer.CurrentCultureIgnoreCase.Equals(string1, string2)

o

StringComparer.CurrentCultureIgnoreCase.Compare(string1, string2)

È un po 'più pulito di string.Equalso string.Comparesovraccarichi che accettano una StringComparisondiscussione.


15
System.Collections.CaseInsensitiveComparer

o

System.StringComparer.OrdinalIgnoreCase

Questo ha effetto sull'intera applicazione?
GateKiller

3
Dove posso trovare maggiori informazioni su questo. Questo significa che posso usare == per una corrispondenza senza distinzione tra maiuscole e minuscole?
GateKiller

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

8

o

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

ma devi assicurarti che StringA non sia null. Quindi probabilmente meglio usare:

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

come ha suggerito John

EDIT: corretto l'errore


4

Puoi usare

if (stringA.equals(StringB, StringComparison.CurrentCultureIgnoreCase))

3

Operatore? No, ma penso che tu possa cambiare la tua cultura in modo che il confronto delle stringhe non sia sensibile al maiuscolo / minuscolo.

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

Sono fiducioso che cambierà il modo in cui le stringhe vengono confrontate dall'operatore uguale.


Sì, per non dire altro non è assolutamente quello che vorresti fare a meno che tu non voglia che tutti i confronti di stringhe non facciano distinzione tra maiuscole e minuscole. Ma penso che cambi il comportamento dell'operatore uguale.
John Leidegren,

3

Ecco un'idea per semplificare la sintassi:

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

Utilizzabile come:

Console.WriteLine((IgnoreCase) "a" == "b"); // false
Console.WriteLine((IgnoreCase) "abc" == "abC"); // true
Console.WriteLine((IgnoreCase) "Abc" == "aBc"); // true
Console.WriteLine((IgnoreCase) "ABC" == "ABC"); // true

Mentre mi piace la sintassi di utilizzo dall'aspetto pulito , è un po 'fuorviante ( IgnoreCasevs IgnoreCaseString) e ambigua (Java sceglie unboxing implicito vs boxing implicito, quindi credo che questo non funzionerebbe in Java con il cast implicito di nuovo in stringa lì). E questo crea l'overhead di memoria di 2 nuovi oggetti con l'esecuzione dell'albero delle chiamate per ogni confronto saltando in diverse chiamate di metodi nidificati per il caso d'uso visualizzato. Detto questo, nella maggior parte dei casi le prestazioni sono probabilmente abbastanza buone.
Arkaine55,

Sebbene questa sia un'idea intelligente , non è davvero saggia dal punto di vista della manutenibilità. Stai effettivamente creando un tipo di stringa surrogato invece di utilizzare il tipo di stringa incorporato nel sistema. Il programmatore che viene dopo non capirà cosa sta succedendo a colpo d'occhio e poi ti maledirà. Usare string.Equals () non è poi così male e la maggior parte delle persone capirà cosa sta facendo.
ntcolonel

1

Sono così abituato a scrivere alla fine di questi metodi di confronto: , StringComparison.

Quindi ho fatto un'estensione.

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

Basta notare che sarà necessario verificare la presenza di null thisStringprima di chiamare ext.


1
È lo stesso di questo metodo integrato nelle attuali versioni di .NET Framework? docs.microsoft.com/en-gb/dotnet/api/…
Bernard Vander Beken

1
Sembra così. Sembra che le versioni successive di .net lo includano ora.
Valamas,

Disponibile da .NET 4.5 e tutte le versioni di .NET Core.
Bernard Vander Beken,


0
if (StringA.ToUpperInvariant() == StringB.ToUpperInvariant()) {

Le persone segnalano che ToUpperInvariant () è più veloce di ToLowerInvariant ().


1
Invariante potrebbe essere una cattiva idea se la cultura attuale o desiderata ha regole speciali per le maiuscole.
OregonGhost

Questo crea una nuova copia di ogni stringa? Se è così, cattiva idea.
cjk

1
Ciò genererà anche un'eccezione se una (o entrambe) stringhe sono null.
tvanfosson,

3
Per quanto riguarda le prestazioni, questa non è una buona soluzione in quanto creerai anche qui 2 nuove istanze di stringa.
Frederik Gheysels,

0

Altri rispondono qui sono totalmente validi, ma in qualche modo ci vuole un po 'di tempo per scrivere StringComparison.OrdinalIgnoreCasee usare String.Compare.

Ho codificato un semplice metodo di estensione String, in cui è possibile specificare se il confronto fa distinzione tra maiuscole e minuscole o insensato con booleano - vedere la risposta seguente:

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.