Domanda

Ho una condizione in un'applicazione silverlight che confronta 2 stringhe, per qualche motivo quando uso == restituisce false mentre .Equals () restituisce vero .

Ecco il codice:

if (((ListBoxItem)lstBaseMenu.SelectedItem).Content.Equals("Energy Attack"))
{
    // Execute code
}

if (((ListBoxItem)lstBaseMenu.SelectedItem).Content == "Energy Attack")
{
    // Execute code
}

Qualche motivo per cui questo sta accadendo?

È stato utile?

Soluzione

Quando == viene utilizzato su un'espressione di tipo oggetto , si risolverà in System.Object.ReferenceEquals .

Equals è solo un < code> virtual e si comporta come tale, quindi verrà utilizzata la versione sovrascritta (che, per il tipo string confronta i contenuti).

Altri suggerimenti

Quando si confronta un riferimento a un oggetto con una stringa (anche se il riferimento a un oggetto si riferisce a una stringa), il comportamento speciale dell'operatore == specifico della classe stringa viene ignorato.

Normalmente (quando non si tratta di stringhe, cioè), Equals confronta i valori , mentre == confronta i riferimenti agli oggetti . Se due oggetti che stai confrontando si riferiscono alla stessa esatta istanza di un oggetto, entrambi restituiranno true, ma se uno ha lo stesso contenuto e proviene da un'origine diversa (è un'istanza separata con gli stessi dati), solo Equals ritorna vero. Tuttavia, come notato nei commenti, stringa è un caso speciale perché sovrascrive l'operatore == in modo che quando si tratta esclusivamente di riferimenti a stringhe (e non riferimenti a oggetti), vengono confrontati solo i valori anche se sono istanze separate. Il seguente codice illustra le sottili differenze nei comportamenti:

string s1 = "test";
string s2 = "test";
string s3 = "test1".Substring(0, 4);
object s4 = s3;
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s2), s1 == s2, s1.Equals(s2));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s3), s1 == s3, s1.Equals(s3));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s4), s1 == s4, s1.Equals(s4));

L'output è:

True True True
False True True
False False True

== e .Equals dipendono entrambi dal comportamento definito nel tipo effettivo e dal tipo effettivo nel sito della chiamata. Entrambi sono solo metodi / operatori che possono essere sovrascritti su qualsiasi tipo e dato qualsiasi comportamento l'autore desideri. Nella mia esperienza, trovo che le persone implementino .Equals su un oggetto ma trascurano di implementare l'operatore == . Ciò significa che .Equals misurerà effettivamente l'uguaglianza dei valori mentre == misurerà se sono o meno lo stesso riferimento.

Quando lavoro con un nuovo tipo la cui definizione è in evoluzione o quando scrivo algoritmi generici, trovo che la migliore pratica sia la seguente

  • Se voglio confrontare i riferimenti in C #, uso direttamente Object.ReferenceEquals (non necessario nel caso generico)
  • Se voglio confrontare i valori, utilizzo EqualityComparer<T>.Default

In alcuni casi, quando ritengo che l'uso di == sia ambiguo, userò esplicitamente Object.Reference uguale al codice per rimuovere l'ambiguità.

Eric Lippert ha recentemente pubblicato un post sul blog sul motivo per cui ci sono 2 metodi di uguaglianza nel CLR. Vale la pena leggere

In primo luogo, c'è una differenza. Per i numeri

> 2 == 2.0
True

> 2.Equals(2.0)
False

E per le stringhe

> string x = null;
> x == null
True

> x.Equals(null)
NullReferenceException

In entrambi i casi, == si comporta in modo più utile di .Equals

Aggiungo che se lanci il tuo oggetto su una stringa, funzionerà correttamente. Questo è il motivo per cui il compilatore ti darà un avvertimento dicendo:

  

Possibile confronto di riferimento non intenzionale; per ottenere un confronto di valore,   cast il lato sinistro per digitare 'string'

== Operatore 1. Se gli operandi sono Tipi di valore e i loro valori sono uguali, restituisce vero altrimenti falso. 2. Se gli operandi sono Tipi di riferimento con l'eccezione della stringa ed entrambi si riferiscono a stesso oggetto, restituisce vero altrimenti falso. 3. Se gli operandi sono di tipo stringa e i loro valori sono uguali, restituisce true else false.

.equals 1. Se gli operandi sono tipi di riferimento, esegue Uguaglianza di riferimento cioè se entrambi si riferiscono allo stesso oggetto, restituisce true altrimenti false. 2. Se gli operandi sono tipi di valore, a differenza dell'operatore == verifica prima il loro tipo e se i loro tipi sono uguali esegue l'operatore == altrimenti restituisce false.

Per quanto ho capito, la risposta è semplice:

  1. == confronta i riferimenti agli oggetti.
  2. .Equals confronta il contenuto dell'oggetto.
  3. I tipi di dati stringa agiscono sempre come confronto dei contenuti.

Spero di aver ragione e che abbia risposto alla tua domanda.

Poiché la versione statica del metodo .Equal non è stata menzionata finora, vorrei aggiungerla qui per riassumere e confrontare le 3 varianti.

MyString.Equals("Somestring"))          //Method 1
MyString == "Somestring"                //Method 2
String.Equals("Somestring", MyString);  //Method 3 (static String.Equals method) - better

dove MyString è una variabile che proviene da qualche altra parte del codice.

Informazioni sullo sfondo e per l'estate:

In Java non è necessario utilizzare == per confrontare le stringhe. Ne parlo nel caso in cui sia necessario utilizzare entrambe le lingue e anche per farti sapere che l'uso di == può anche essere sostituito con qualcosa di meglio in C #.

In C # non c'è alcuna differenza pratica per confrontare le stringhe usando il Metodo 1 o il Metodo 2 purché entrambi siano di tipo stringa. Tuttavia, se uno è nullo, uno è di un altro tipo (come un numero intero) o rappresenta un oggetto con un riferimento diverso, quindi, come mostra la domanda iniziale, potresti riscontrare che il confronto del contenuto per l'uguaglianza potrebbe non restituire ciò che ti aspetti.

Soluzione suggerita:

Poiché l'uso di == non è esattamente uguale all'utilizzo di .Equals quando si confrontano le cose, è possibile utilizzare il metodo String.Equals statico anziché. In questo modo, se le due parti non sono dello stesso tipo, confronterai comunque il contenuto e se uno è nullo, eviterai l'eccezione.

   bool areEqual = String.Equals("Somestring", MyString);  

È un po 'di più da scrivere, ma secondo me è più sicuro da usare.

Ecco alcune informazioni copiate da Microsoft:

public static bool Equals (string a, string b);

I parametri

a String

La prima stringa da confrontare, o null .

b String

La seconda stringa da confrontare, o null .

Restituisce Boolean

true se il valore di a è uguale al valore di b ; altrimenti, false . Se sia a che b sono null , il metodo restituisce true .

Sono un po 'confuso qui. Se il tipo di runtime di Content è di tipo string, allora sia == che Equals dovrebbero restituire true. Tuttavia, poiché questo non sembra essere il caso, il tipo di runtime di Content non è una stringa e la chiamata Equals su di esso sta facendo un'uguaglianza referenziale e questo spiega perché l'Equals ("Attacco di energia") fallisce. Tuttavia, nel secondo caso, la decisione su quale sovraccarico == operatore statico dovrebbe essere chiamato viene presa al momento della compilazione e questa decisione sembra essere == (stringa, stringa). questo mi suggerisce che il contenuto fornisce una conversione implicita in stringa.

Esiste un'altra dimensione a una risposta precedente di @BlueMonkMN. La dimensione aggiuntiva è che la risposta alla domanda sul titolo di @ Drahcir, come viene affermato, dipende anche da come siamo arrivati ??al valore string . Per illustrare:

string s1 = "test";
string s2 = "test";
string s3 = "test1".Substring(0, 4);
object s4 = s3;
string s5 = "te" + "st";
object s6 = s5;
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s2), s1 == s2, s1.Equals(s2));

Console.WriteLine("\n  Case1 - A method changes the value:");
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s3), s1 == s3, s1.Equals(s3));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s4), s1 == s4, s1.Equals(s4));

Console.WriteLine("\n  Case2 - Having only literals allows to arrive at a literal:");
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s5), s1 == s5, s1.Equals(s5));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s6), s1 == s6, s1.Equals(s6));

L'output è:

True True True

  Case1 - A method changes the value:
False True True
False False True

  Case2 - Having only literals allows to arrive at a literal:
True True True
True True True

Aggiungendo un altro punto alla risposta.

Il metodo

.EqualsTo () ti offre la possibilità di confrontare con cultura e maiuscole / minuscole.

Proprio come un'aggiunta alle risposte già buone: questo comportamento NON è limitato alle stringhe o al confronto di diversi tipi di numeri. Anche se entrambi gli elementi sono di tipo oggetto dello stesso tipo sottostante. & Quot; == " non funzionerà.

La seguente schermata mostra i risultati del confronto tra due oggetti {int} - valori

 Esempio da VS2017

Il token == in C # viene utilizzato per due diversi operatori di controllo dell'uguaglianza. Quando il compilatore incontra quel token, controllerà se uno dei tipi confrontati ha implementato un sovraccarico operatore-uguaglianza per i tipi di combinazione specifici da confrontare (*) o per una combinazione di tipi in cui entrambi i tipi possono essere convertiti. Se il compilatore rileva un tale sovraccarico, lo utilizzerà. Altrimenti, se i due tipi sono entrambi tipi di riferimento e non sono classi non correlate (o possono essere un'interfaccia o possono essere classi correlate), il compilatore considererà == come operatore di confronto dei riferimenti . Se nessuna delle due condizioni si applica, la compilazione fallirà.

Nota che alcune altre lingue usano token separati per i due operatori di controllo di uguaglianza. In VB.NET, ad esempio, il token = viene utilizzato all'interno delle espressioni esclusivamente per l'operatore di verifica dell'uguaglianza sovraccaricabile e Is viene utilizzato come test di riferimento o null- operatore di prova. L'utilizzo di = su un tipo che non sostituisce l'operatore di verifica dell'uguaglianza non riuscirà, così come il tentativo di utilizzare Is per scopi diversi dalla verifica dell'uguaglianza o della nullità di riferimento.

(*) I tipi generalmente sovraccaricano l'uguaglianza solo per il confronto con se stessi, ma può essere utile per i tipi sovraccaricare l'operatore di uguaglianza per il confronto con altri tipi particolari; per esempio, int avrebbe potuto (e IMHO avrebbe dovuto, ma non avrebbe), definito un operatore di uguaglianza per il confronto con float , in modo tale che 16777217 non si riferisse uguale a 16777216f. Così com'è, dal momento che nessun operatore di questo tipo è definito, C # promuoverà int in float , arrotondandolo a 16777216f prima che l'operatore di controllo dell'uguaglianza lo veda; quell'operatore vede quindi due numeri uguali in virgola mobile e li riporta come uguali, ignari dell'arrotondamento che ha avuto luogo.

Risposte ed esempi davvero fantastici!

Vorrei solo aggiungere la differenza fondamentale tra i due

  

Operatori come == non sono polimorfici, mentre Equals è

Con questo concetto in mente, se elaborate qualche esempio (osservando il tipo di riferimento della mano sinistra e della destra e verificando / sapendo se il tipo ha effettivamente == l'operatore è sovraccarico e gli uguali vengono sostituiti) siete certi di ottenere la risposta giusta.

Quando creiamo un oggetto ci sono due parti nell'oggetto, uno è il contenuto e l'altro è riferimento a quel contenuto. == confronta sia contenuto che riferimento; equals () confronta solo i contenuti

http: // www. codeproject.com/Articles/584128/What-is-the-difference-between-equalsequals-and-Eq

==

L'operatore == può essere utilizzato per confrontare due variabili di qualsiasi tipo e confronta semplicemente i bit .

int a = 3;
byte b = 3;
if (a == b) { // true }

Nota: ci sono più zero sul lato sinistro dell'int ma ma non ci interessa a questo.

int a (00000011) == byte b (00000011)

Ricorda == l'operatore si preoccupa solo del modello dei bit nella variabile.

Usa == Se due riferimenti (primitivi) si riferiscono allo stesso oggetto nell'heap.

Le regole sono le stesse se la variabile è un riferimento o una primitiva.

Foo a = new Foo();
Foo b = new Foo();
Foo c = a;

if (a == b) { // false }
if (a == c) { // true }
if (b == c) { // false }

a == c è vero a == b è falso

il modello di bit è lo stesso per a e c, quindi sono uguali usando ==.

Equal ():

Utilizza il metodo equals () per vedere se due oggetti diversi sono uguali .

Come due diversi oggetti String che rappresentano entrambi i caratteri in " Jane "

L'unica differenza tra Equal e == sta nel confronto del tipo di oggetto. in altri casi, come tipi di riferimento e tipi di valore, sono quasi uguali (entrambi sono uguaglianza bit-bit o entrambi sono uguaglianza di riferimento).

oggetto: Uguali: uguaglianza bit-saggia ==: uguaglianza di riferimento

stringa: (equivale e == sono gli stessi per la stringa, ma se una stringa è cambiata in oggetto, il risultato del confronto sarà diverso) Uguali: uguaglianza bit-saggia ==: uguaglianza bit-saggia

Vedi qui per ulteriori spiegazioni.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top