C # różnica między = = i równa()

Mam warunek w aplikacji silverlight, który porównuje 2 ciągi znaków, z jakiegoś powodu, gdy używam ==zwraca false podczas gdy .Equals()zwraca true.

Oto kod:

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

if (((ListBoxItem)lstBaseMenu.SelectedItem).Content == "Energy Attack")
{
    // Execute code
}
Jakiś powód, dlaczego tak się dzieje?
 441
Author: poke, 2009-05-02

16 answers

Gdy == Jest użyte w wyrażeniu typu object, to System.Object.ReferenceEquals.

Equals jest tylko metodą virtual i zachowuje się tak, więc zostanie użyta nadpisana wersja(która dla typu string porównuje zawartość).

 361
Author: Mehrdad Afshari,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-16 09:30:16

Podczas porównywania odniesienia do obiektu z łańcuchem znaków (nawet jeśli odniesienie do obiektu odnosi się do łańcucha znaków), specjalne zachowanie operatora == specyficznego dla klasy string jest ignorowane.

Normalnie (gdy nie ma do czynienia z łańcuchami), Equalsporównuje wartości, podczas gdy ==porównuje odniesienia do obiektów. Jeśli dwa obiekty, które porównujesz odnoszą się do tej samej instancji obiektu, to oba zwracają true, ale jeśli jeden ma tę samą zawartość i pochodzi z inne źródło (jest osobną instancją z tymi samymi danymi), tylko Equals zwróci true. Jednak, jak zauważono w komentarzach, łańcuch znaków jest szczególnym przypadkiem, ponieważ nadpisuje operator ==, tak że w przypadku czysto ciągowych odniesień (a nie odniesień do obiektów) porównywane są tylko wartości, nawet jeśli są oddzielnymi instancjami. Poniższy kod ilustruje subtelne różnice w zachowaniach:

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

Wyjście to:

True True True
False True True
False False True
 252
Author: BlueMonkMN,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-27 21:22:14

== i .Equals są zależne od zachowania zdefiniowanego w rzeczywistym typie I rzeczywistym typie w miejscu wywołania. Obie są tylko metodami / operatorami, które mogą być nadpisane na dowolny typ i dowolne zachowanie autora tak chce. Z mojego doświadczenia wynika, że często ludzie implementują .Equals na obiekcie, ale zaniedbują zaimplementowanie operatora ==. Oznacza to, że .Equals faktycznie zmierzy równość wartości, podczas gdy == zmierzy, czy są one takie same Referencja.

Kiedy pracuję z nowym typem, którego definicja jest w strumieniu lub piszę algorytmy generyczne, uważam, że najlepszą praktyką jest następująca

  • jeśli chcę porównać referencje w C#, używam Object.ReferenceEquals bezpośrednio (nie potrzebne w przypadku generycznym)
  • Jeśli chcę porównać wartości używam EqualityComparer<T>.Default

W niektórych przypadkach, gdy czuję, że użycie == jest niejednoznaczne, użyję jawnie Object.Reference equals w kodzie, aby usunąć niejednoznaczność.

Eric Lippert napisał niedawno post na blogu na temat dlaczego istnieją 2 metody równości w CLR. Warto przeczytać

 42
Author: JaredPar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-29 21:38:42

Po pierwsze, istnieje jest różnica. Dla liczb

> 2 == 2.0
True

> 2.Equals(2.0)
False

I dla strun

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

> x.Equals(null)
NullReferenceException

W obu przypadkach == zachowuje się bardziej użytecznie niż .Equals

 16
Author: Colonel Panic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-15 13:15:23

Dodam, że jeśli rzucisz swój obiekt na ciąg znaków, to będzie on działał poprawnie. Dlatego kompilator da ci Ostrzeżenie mówiąc:

Możliwe niezamierzone porównanie referencji; aby uzyskać porównanie wartości, rzuć lewą stronę, aby wpisać "string"

 12
Author: MikeKulls,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-12 13:44:54

== Operator 1. Jeśli operandy są typami wartości i ich wartości są równe, zwraca true else false. 2. Jeśli operandy są typami referencji z wyjątkiem string i oba odnoszą się do tego samego obiektu, zwraca true else false. 3. Jeśli operandy są typu string i ich wartości są równe, to zwraca true else false.

.Equals 1. Jeśli operandy są typami referencji, to wykonuje równość referencji to znaczy, jeśli oba odwołują się do tego samego obiektu, zwraca prawda inaczej fałsz. 2. Jeśli operandy są typami wartości, to w przeciwieństwie do operatora = = sprawdza najpierw ich typ, A jeśli ich typy są takie same, wykonuje operator = = else zwraca false.

 8
Author: kashif,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-14 04:31:40

Z tego co rozumiem odpowiedź jest prosta:

  1. == porównuje odniesienia do obiektów.
  2. .Equals porównuje zawartość obiektu.
  3. typy danych łańcuchowych zawsze działają jak porównywanie treści.

Mam nadzieję, że mam rację i że odpowiedziała na twoje pytanie.

 8
Author: Liraz Shaka Amir,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-27 09:56:45

Trochę się pogubiłem. Jeżeli Runtime typ zawartości jest typu string, wtedy zarówno = = jak i Equals powinny zwracać true. Ponieważ jednak tak nie jest, wtedy runtime type of Content nie jest string i wywołanie Equals na nim powoduje referencyjną równość i wyjaśnia to, dlaczego Equals("Energy Attack") nie powiedzie się. Jednak w drugim przypadku decyzja o tym, który operator overloaded == statyczny powinien być wywołany, jest podejmowana w czasie kompilacji i wydaje się, że decyzja ta jest = = (string, string)== sugeruje to mi, że treść zapewnia ukrytą konwersję na ciąg znaków.

 2
Author: Mehmet Aras,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-02 16:02:44

Istnieje inny wymiar wcześniejszej odpowiedzi @ BlueMonkMN. Dodatkowym wymiarem jest to, że odpowiedź na pytanie tytułowe @ Drahcir, jak to zostało powiedziane, zależy również od Jak dotarliśmy do wartości string. Do zilustrowania:

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

Wyjście to:

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
 2
Author: Novichok,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-13 18:01:30

Dodanie jeszcze jednego punktu do odpowiedzi.

.EqualsTo() metoda daje możliwość porównania z kulturą i rozróżniania wielkości liter.

 2
Author: Bala,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-25 07:23:08

Ponieważ statyczna Wersja metody .Equal nie została do tej pory wymieniona, chciałbym dodać to tutaj, aby podsumować i porównać 3 warianty.

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

Gdzie {[4] } jest zmienną pochodzącą z innego miejsca w kodzie.

Informacje ogólne i do summerize:

W Javie nie należy używać == do porównywania łańcuchów. Wspominam o tym w przypadku, gdy trzeba używać obu języków, a także aby poinformować, że za pomocą == można również zastąpić z czymś lepszym w C#.

W C# nie ma praktycznej różnicy w porównywaniu łańcuchów za pomocą metody 1 lub metody 2, o ile oba są typu string. Jednakże, jeśli jeden jest null, jeden jest innego typu (jak liczba całkowita) lub reprezentuje obiekt, który ma inne odniesienie, to, jak pokazuje początkowe pytanie, możesz doświadczyć, że porównywanie zawartości dla równości może nie zwrócić tego, czego oczekujesz.

Sugerowane rozwiązanie:

Ponieważ za pomocą == nie jest dokładnie tym samym, co użycie .Equals podczas porównywania rzeczy, można użyć statycznego ciągu .Równa się zamiast metody. W ten sposób, jeśli obie strony nie są tego samego typu, nadal porównujesz zawartość, a jeśli jedna jest null, unikniesz wyjątku.

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

To trochę więcej do napisania, ale moim zdaniem bezpieczniejsze w użyciu.

Oto kilka informacji skopiowanych z Microsoftu:

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

Parametry

a String

Pierwszy ciąg do porównaj, lub null.

b String

Drugi ciąg do porównania, lub null.

Zwraca Boolean

true Jeśli wartość a jest taka sama jak wartość b; w przeciwnym razie false. Jeśli zarówno a, jak i bnull, metoda zwraca true.

 2
Author: levteck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-04 20:35:18

Token == W C# jest używany dla dwóch różnych operatorów sprawdzania równości. Gdy kompilator napotka ten token, sprawdzi, czy któryś z porównywanych typów zaimplementował przeciążenie operatora równości dla porównywanych typów kombinacji (*), lub dla kombinacji typów, na które oba typy mogą być przekonwertowane. Jeśli kompilator znajdzie takie przeciążenie, użyje go. W przeciwnym razie, jeśli oba typy są zarówno typami odniesienia i nie są ze sobą powiązane klasy (albo mogą być interfejsem, albo mogą być klasami pokrewnymi), kompilator będzie traktował == jako operator porównywania referencji. Jeśli żaden warunek nie zostanie zastosowany, kompilacja nie powiedzie się.

Zauważ, że niektóre inne języki używają osobnych tokenów dla dwóch operatorów sprawdzania równości. W VB.NET na przykład token = jest używany w wyrażeniach wyłącznie dla przeciążalnego operatora sprawdzania równości, a {[3] } jest używany jako operator reference-test lub null-test. An TO use = on a typ, który nie nadpisuje operatora equality-check, zakończy się niepowodzeniem, podobnie jak próba użycia Is w jakimkolwiek celu innym niż testowanie równości odniesienia lub nullity.

(*)typy Zwykle przeciążają równość dla porównania z sobą, ale może być przydatne dla typów przeciążać operator równości dla porównania z innymi szczególnymi typami; na przykład, int może mieć (a IMHO powinien mieć, ale nie) zdefiniowane operatory równości dla porównania z float, tak że 16777217 nie zgłasza się jako równe 16777216f. ponieważ nie zdefiniowano takiego operatora, C# będzie promować int do float, zaokrąglając go do 16777216f, zanim Operator equality-check go zobaczy; operator ten widzi dwie równe liczby zmiennoprzecinkowe i zgłasza je jako równe, nieświadomy zaokrąglenia, które miało miejsce.

 0
Author: supercat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-14 17:47:05

Naprawdę świetne odpowiedzi i przykłady!

Chciałbym tylko dodać podstawową różnicę między tymi dwoma,

Operatory takie jak == nie są polimorficzne, natomiast Equals to

Mając to na uwadze, jeśli wypracujesz jakiś przykład (patrząc na typ odniesienia lewej i prawej ręki i sprawdzając / wiedząc, czy typ rzeczywiście ma przeciążony operator = = i jest równy nadrzędnemu), masz pewność, że otrzymasz właściwą odpowiedź.

 0
Author: Manish Basantani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-15 09:10:38

Kiedy tworzymy dowolny obiekt, do obiektu należą dwie części, jedna jest treścią, a druga jest odniesieniem do tej treści. == porównuje zarówno treść, jak i odniesienie; equals() porównuje tylko zawartość

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

 -1
Author: user3440463,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-20 04:49:49

==

Operator = = może być użyty do porównania dwóch zmiennych dowolnego rodzaju, a po prostu porównuje bity .

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

Uwaga: po lewej stronie INT jest więcej zer, ale nie dbamy o to tutaj.

Int a (00000011) == bajt b (00000011)

Remember = = operator dba tylko o wzór bitów w zmiennej.

Użyj = = jeśli dwa odwołania (primitives) odnoszą się do tego samego obiektu na / align = "left" /

Zasady są takie same, niezależnie od tego, czy zmienna jest odniesieniem, czy prymitywem.

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 jest prawdą a = = B is false

Wzorce bitowe są takie same dla a i c, więc są równe przy użyciu==.

równe():

Użyj metody equals (), aby zobaczyć czy dwa różne obiekty są równe .

Takie jak dwa różne obiekty łańcuchowe, które oba reprezentują znaki w "Jane"

 -2
Author: Sanchit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-15 11:34:26

Jedyną różnicą pomiędzy Equal i = = jest porównanie typu obiektu. w innych przypadkach, takich jak typy referencyjne i typy wartości, są one prawie takie same (albo oba są równością bitową, albo oba są równością referencyjną).

Obiekt: Equals: bit-wise equality = = : równość odniesienia

String: (równe i = = są takie same dla string, ale jeżeli jeden z łańcuchów zmieni się na obiekt, wtedy wynik porównania będzie inny) Equals: bit-wise equality = = = bit-wise równość

Zobacz tutaj aby uzyskać więcej wyjaśnień.

 -2
Author: Will Yu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-30 02:11:37