Różnica w C # między == a Equals ()


548

Mam warunek w aplikacji silverlight, która porównuje 2 łańcuchy, z jakiegoś powodu, gdy ==go używam , zwraca false, a .Equals()zwraca true .

Oto kod:

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

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

Masz powód, dlaczego tak się dzieje?



8
Ciąg zastępuje ==, ale operatory nie są polimorficzne. W tym kodzie ==operator jest wywoływany według typu object, który dokonuje porównania tożsamości zamiast wartości.
Drew Noakes

12
Aby rozwinąć komentarz @DrewNoakes: Kompilator wybiera ==przeciążenie na podstawie typu argumentów czasu kompilacji. ContentNieruchomość object. Operatory nie są wirtualne, więc ==wywoływana jest domyślna implementacja , dająca porównanie równości odniesienia. W przypadku Equals wywołanie przechodzi do metody wirtualnej object.Equals(object); stringprzesłania tę metodę i wykonuje porządkowe porównanie zawartości ciągu. Zobacz msdn.microsoft.com/en-us/library/fkfd9eh8(v=vs.110).aspx i referenceource.microsoft.com/#mscorlib/system/string.cs,507 .
phoog

6
Wyjaśnienie @ phoog jest dokładne. Należy zauważyć, że gdy lewa strona ==ma typ czasu kompilacji, objecta prawa strona ma typ czasu kompilacji string, wówczas kompilator C # musi wybrać (problematyczne, w tym przypadku) przeciążenie operator ==(object, object); ale to będzie wydawać ostrzeżenia w czasie kompilacji, że może to być niezamierzona. Przeczytaj więc ostrzeżenia dotyczące czasu kompilacji! Aby rozwiązać problem i nadal używać ==, przesuń lewą stronę na string. Jeśli dobrze pamiętam, tekst ostrzegawczy sugeruje właśnie to.
Jeppe Stig Nielsen,

1
@JeppeStigNielsen +1 za poradę, aby przeczytać ostrzeżenia kompilatora. Jeszcze lepiej: włącz opcję ostrzeżeń jako błędów, aby zmusić wszystkich do zwrócenia na nie uwagi.
phoog

Odpowiedzi:


429

Kiedy ==zostanie użyty do wyrażenia typu object, rozpozna System.Object.ReferenceEquals.

Equalsjest tylko virtualmetodą i zachowuje się jako taka, więc zostanie użyta przesłonięta wersja (która dla stringtypu porównuje zawartość).


56
Chyba że operator jest konkretnie zaimplementowany w klasie
Dominic Cronin,

23
@DominicCronin To nie jest prawda. Nawet jeśli == jest zaimplementowane w klasie, zostanie zignorowane, ponieważ typ po lewej stronie porównania to obiekt. Wygląda na to, że przeciążenia operatora są określane w czasie kompilacji, a podczas kompilacji wszystko, co wie, to to, że lewa strona jest obiektem.
MikeKulls

4
@DominicCronin Uważam, że twoje pierwsze stwierdzenie jest poprawne, ponieważ == podejmie decyzję o sprzeciwie, ale drugie stwierdzenie, że przeciążenie operatora rozwiązuje w podobny sposób, nie jest. Różnią się od siebie i dlatego .Equals rozpozna ciąg znaków, podczas gdy == podejmie decyzję o sprzeciwie.
MikeKulls,

8
Dla jasności, objectpismo (zwróć uwagę na czcionkę monospace) technicznie ma być „wyrażeniem typu System.Object”. Nie ma to nic wspólnego z typem wykonawczym instancji, do której odwołuje się wyrażenie. Myślę, że stwierdzenie „operatory zdefiniowane przez użytkownika są traktowane jak virtualmetody” jest bardzo mylące. Są one traktowane jak przeciążone metody i zależą tylko od typu argumentów w czasie kompilacji. W rzeczywistości, po obliczeniu zbioru kandydujących operatorów zdefiniowanych przez użytkownika, resztą procedury wiązania będzie dokładnie algorytm rozstrzygania przeciążenia metody
Mehrdad Afshari

4
@DominicCronin Mylącą częścią jest to, że virtualrozdzielczość metody zależy od faktycznego typu środowiska wykonawczego instancji, podczas gdy jest to całkowicie ignorowane w rozwiązaniu przeciążenia operatora, i to jest właśnie sedno mojej odpowiedzi.
Mehrdad Afshari,

314

Podczas porównywania odwołania do obiektu do łańcucha (nawet jeśli odwołanie do obiektu odnosi się do łańcucha), specjalne zachowanie ==operatora specyficzne dla klasy łańcucha jest ignorowane.

Zwykle (gdy nie ma do czynienia z łańcuchami), Equalsporównuje wartości , a ==porównuje odwołania do obiektów . Jeśli dwa porównywane obiekty odnoszą się do tej samej dokładnej instancji obiektu, wówczas oba zwrócą wartość true, ale jeśli jeden ma tę samą treść i pochodzi z innego źródła (jest osobną instancją z tymi samymi danymi), tylko równa się zwróć prawdę. Jednak, jak zauważono w komentarzach, ciąg znaków jest szczególnym przypadkiem, ponieważ przesłania ==operator, tak więc w przypadku czysto odwołań do ciągów (a nie odwołań do obiektów) porównywane są tylko wartości, nawet jeśli są to osobne wystąpienia. 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));

Dane wyjściowe to:

True True True
False True True
False False True

8
Spot on. Operator „==” porównuje odwołania do obiektów (płytkie porównanie), a .Equals () porównuje zawartość obiektów (głębokie porównanie). Jak powiedział @mehrdad, .Equals () jest nadpisane, aby zapewnić dokładne porównanie zawartości.
Andrew

1
Zostawię ten post tutaj, ponieważ uważam, że warto podkreślić to, co się nie dzieje, ponieważ trzeba uważnie obserwować, aby to zrozumieć. (I myślę, że warto też wykazać kod do poprawnego i niepoprawnego zrozumienia.) Mam nadzieję, że ocena nie spadnie poniżej 0.
BlueMonkMN

5
Z pewnością String implementuje niestandardowy operator ==. Jeśli nie, użycie == nie porównałoby treści. Dlatego String jest złym przykładem do zastosowania tutaj, ponieważ nie pomaga nam zrozumieć ogólnego przypadku, w którym nie zdefiniowano żadnego operatora niestandardowego.
Dominic Cronin,

6
+1 za epicki przykład kodu, który sprawił, że zrozumiałem to. Pokazuje ogólny przypadek typu statycznego (typ po lewej stronie) będącego przedmiotem oraz szczególny przypadek typu statycznego (typ / RHS) będącego łańcuchem. I dobrze dotyka internowania strun.
barlop

2
@badsamaritan Z powodu internowania strun
Alexander Derck

46

==i .Equalsoba są zależne od zachowania określonego w rzeczywistym typie i rzeczywistym typie w miejscu połączenia. Obie są tylko metodami / operatorami, które można zastąpić dowolnym rodzajem i biorąc pod uwagę dowolne zachowanie, które autor sobie zażyczy. Z mojego doświadczenia wynika, że ​​ludzie często implementują .Equalsna obiekcie, ale zaniedbują implementację operatora ==. Oznacza to, że .Equalsfaktycznie będzie mierzyć równość wartości podczas== sprawdzi, czy są one tym samym odniesieniem.

Kiedy pracuję z nowym typem, którego definicja jest zmienna lub piszę ogólne algorytmy, uważam, że najlepsza praktyka jest następująca

  • Jeśli chcę porównać odniesienia w języku C #, używam Object.ReferenceEquals bezpośrednio (nie jest to konieczne w przypadku ogólnym)
  • Jeśli chcę porównać wartości, których używam EqualityComparer<T>.Default

W niektórych przypadkach, gdy uważam, że użycie ==jest niejednoznaczne, jawnie Object.Referenceużyję znaku równości w kodzie, aby usunąć niejednoznaczność.

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


Cóż, Jared, bezpośrednio naruszasz słynny Jeff: „Najlepszym kodem jest tutaj żaden kod”. Czy to naprawdę uzasadnione? Z drugiej strony widzę, skąd to się bierze i dlaczego wskazane jest wyraźne określenie semantyki. W tym przypadku bardzo wolę sposób, w jaki VB radzi sobie z równością obiektów. Jest krótki i jednoznaczny.
Konrad Rudolph

@Konrad, naprawdę powinienem był powiedzieć „kiedy nie jestem zaznajomiony z typem, uważam, że najlepsza praktyka jest następująca”. Tak, VB ma tutaj znacznie lepszą semantykę, ponieważ naprawdę oddziela równość wartości i odniesienia. C # miesza oba razem i czasami powoduje błędy niejednoznaczności.
JaredPar

10
To nie do końca prawda. == nie można zastąpić, jest to metoda statyczna. Można go tylko przeciążać, co jest ważną różnicą. Tak więc kod wykonywany dla operatora == jest łączony w czasie kompilacji, a Equals jest wirtualny i znajduje się w czasie wykonywania.
Stefan Steinegger,

20

== Operator

  1. Jeśli operandy są typami wartości, a ich wartości są równe, zwraca true, w przeciwnym razie false.
  2. Jeśli operandy są typami referencyjnymi z wyjątkiem łańcucha i oba odnoszą się do tej samej instancji (tego samego obiektu), wówczas zwraca true lub false.
  3. Jeśli operandy mają ciąg znaków, a ich wartości są równe, to zwraca true, w przeciwnym razie false.

.Równa się

  1. Jeśli operandy są typami referencyjnymi , wykonuje równość referencyjną, tzn. Jeśli oba odnoszą się do tej samej instancji (tego samego obiektu), zwraca true, w przeciwnym razie false.
  2. Jeśli argumenty są typami wartości, to w przeciwieństwie do operatora ==, najpierw sprawdza ich typ, a jeśli ich typy są takie same, operator ==, w przeciwnym razie zwraca false.

2
To nie jest poprawne. ==Operator może być przeciążony dla każdego rodzaju, nie tylko strun. Opisanie wyjątku specjalnego przypadku tylko dla ciągu znaków wprowadza w błąd semantykę operatora. Bardziej dokładne, choć być może nie byłoby szczególnie użyteczne, byłoby powiedzenie „jeśli operandy są typami referencyjnymi, zwraca wartość true, jeśli operandy odnoszą się do tego samego obiektu, chyba że występuje odpowiednie przeciążenie, w którym to przypadku implementacja tego przeciążenia określa wynik „. To samo dotyczy Equalsdodanej komplikacji, że jest to metoda wirtualna, więc jej zachowanie może być nadpisane, a także przeciążone.
phoog

19

Po pierwsze, jest różnica. Dla liczb

> 2 == 2.0
True

> 2.Equals(2.0)
False

I na smyczki

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

> x.Equals(null)
NullReferenceException

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


2
Nie jestem pewien, czy uważam przymus typów całkowych za zmiennoprzecinkowe z ==operatorem za dobrą rzecz. Na przykład, czy 16777216.0f powinno być równe (int) 16777217, (podwójne) 16777217.0, oba, czy żadne? Porównania między typami całkowymi są w porządku, ale porównania zmiennoprzecinkowe powinny być wykonywane tylko IMHO z wartościami, które są jawnie rzutowane na pasujące typy. Porównanie a floatdo czegoś innego niż a float, lub doubledo czegoś innego niż a double, uderza mnie jako główny zapach kodu, który nie powinien się kompilować bez diagnozy.
supercat

1
@supercat Zgadzam się - to niepokojące, że x == ynie oznacza x/3 == y/3(spróbuj x = 5i y = 5.0).
Pułkownik Panic

Uważam, że użycie /dzielenia liczb całkowitych jest wadą w projektowaniu C # i Java. Pascal, diva nawet VB.NET ` are much better. The problems with == `są jednak gorsze: x==yi y==znie implikuje tego x==z(rozważ trzy liczby w moim poprzednim komentarzu). Co do relacji sugerujesz, nawet jeśli xi yto zarówno floatalbo oba double, x.equals((Object)y)nie oznacza, że 1.0f/x == 1.0f / y` (jeśli miałem druthers, byłoby zagwarantować, że, nawet jeśli ==nie odróżnia pozytywne i zero, Equalspowinny).
supercat

To normalne, ponieważ pierwszym parametrem Equals () jest ciąg znaków!
Whiplash,

17

O ile rozumiem odpowiedź jest prosta:

  1. == porównuje odwołania do obiektów.
  2. .Equals porównuje zawartość obiektu.
  3. String typy danych zawsze działają jak porównanie zawartości.

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


15

Dodałbym, że jeśli rzutujesz swój obiekt na ciąg, to zadziała on poprawnie. Dlatego kompilator wyświetli ostrzeżenie:

Możliwe niezamierzone porównanie odniesienia; aby uzyskać porównanie wartości, po lewej stronie wpisz „ciąg”


1
Dokładnie. @DominicCronin: Zawsze przestrzegaj ostrzeżeń dotyczących czasu kompilacji. Jeśli tak object expr = XXX; if (expr == "Energy") { ... }, to skoro lewa strona ma czas kompilacji object, kompilator musi użyć przeciążenia operator ==(object, object). Sprawdza równość odniesienia. Czy da to, trueczy falsemoże być trudne do przewidzenia z powodu internowania łańcucha . Jeśli wiesz, że lewa strona jest albo nulltypu string, rzuć lewą stronę na stringprzed użyciem ==.
Jeppe Stig Nielsen

po części w inny sposób. == (przy określaniu, czy używa równości odniesienia czy równości wartości) zależy od typu czasu kompilacji / typu statycznego / typu lewej strony. (taki typ jest rozwiązywany w analizie czasu kompilacji). Zamiast typu środowiska wykonawczego / typu dynamicznego / typu RHS. Kod BlueMonkMN pokazuje to, choć nie z rzutowaniem.
barlop

5

Ponieważ do .Equaltej pory nie wspomniano o statycznej wersji metody, chciałbym dodać ją 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 MyStringjest zmienną pochodzącą z innego miejsca w kodzie.

Informacje w tle i na lato:

W Javie ==do porównywania łańcuchów nie należy używać. Wspominam o tym na wypadek, gdybyś musiał używać obu języków, a także poinformować, że używanie ==można również zastąpić czymś lepszym w języku C #.

W języku C # nie ma praktycznej różnicy w porównywaniu ciągów przy użyciu metody 1 lub metody 2, o ile oba są ciągami typu. Jednakże, jeśli jeden jest pusty, jeden jest innego typu (np. Liczba całkowita) lub jeden reprezentuje obiekt, który ma inne odwołanie, wówczas, jak pokazuje początkowe pytanie, możesz doświadczyć, że porównanie zawartości dla równości może nie zwrócić tego, co oczekujesz.

Sugerowane rozwiązanie:

Ponieważ używanie ==nie jest dokładnie tym samym, co używanie .Equalspodczas porównywania rzeczy, można zamiast tego użyć statycznej metody String.Equals . W ten sposób, jeśli dwie strony nie są tego samego typu, nadal będziesz porównywać zawartość, a jeśli jedna będzie pusta, unikniesz wyjątku.

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

Jest trochę więcej do napisania, ale moim zdaniem bezpieczniejszy w użyciu.

Oto niektóre informacje skopiowane z Microsoft:

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

Parametry

a Strunowy

Pierwszy ciąg do porównania lub null.

b Strunowy

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

Zwroty Boolean

truejeśli wartość ajest taka sama jak wartość b; w przeciwnym razie false. Jeśli oba są ai , metoda zwraca .bnulltrue


5

Tylko jako uzupełnienie już dobrych odpowiedzi: To zachowanie NIE jest ograniczone do ciągów znaków lub porównywania różnych typów liczb. Nawet jeśli oba elementy są typu obiektu tego samego typu bazowego. „==” nie będzie działać.

Poniższy zrzut ekranu pokazuje wyniki porównania dwóch wartości obiektu {int}

Przykład z VS2017


2

Jestem tu trochę zdezorientowany. Jeśli typ środowiska wykonawczego Content ma ciąg znaków, zarówno ==, jak i Equals powinny zwracać wartość true. Ponieważ jednak nie wydaje się, że tak się dzieje, typ zawartości w środowisku wykonawczym nie jest ciągiem, a wywołanie na nim równości powoduje równość referencyjną, co wyjaśnia, dlaczego zawodzi równość („atak energii”). Jednak w drugim przypadku decyzja, który przeciążony operator == statyczny powinien zostać wywołany, jest podejmowana w czasie kompilacji i wydaje się, że ta decyzja to == (ciąg, ciąg). sugeruje mi to, że Treść zapewnia niejawną konwersję na ciąg znaków.


2
Masz to od tyłu do przodu. Na początek Equals („Energy Attack”) nie zawiedzie, == to ten, który zwraca false. == kończy się niepowodzeniem, ponieważ używa == z obiektu, a nie ciągu.
MikeKulls,

Domyślnie operator == sprawdza równość odniesień, określając, czy dwa odniesienia wskazują na ten sam obiekt. Dlatego typy referencyjne nie muszą implementować operatora == w celu uzyskania tej funkcjonalności. Gdy typ jest niezmienny, to znaczy dane zawarte w instancji nie mogą zostać zmienione, przeciążenie operatora == w celu porównania równości wartości zamiast równości odniesienia może być przydatne, ponieważ jako obiekty niezmienne można je traktować tak samo jak długo ponieważ mają tę samą wartość. Nie jest dobrym pomysłem przesłonięcie operatora == w typach niezmiennych.
Wajeed-MSFT

2

Istnieje inny wymiar wcześniejszej odpowiedzi @BlueMonkMN. Dodatkowym wymiarem jest to, że odpowiedź na pytanie tytułowe @ Drahcir, jak zostało powiedziane, zależy również od tego , jak doszliśmy do tej stringwartości. Ilustrować:

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

Dane wyjściowe 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

Dodanie jeszcze jednego punktu do odpowiedzi.

.EqualsTo() ta metoda zapewnia porównanie z kulturą i rozróżnianiem wielkości liter.


0

==Żeton w C # jest używany dla dwóch różnych operatorów równości sprawdzić. Gdy kompilator napotka ten token, sprawdzi, czy którykolwiek z porównywanych typów zaimplementował przeciążenie operatora równości albo dla konkretnych typów kombinacji, które są porównywane (*), czy dla kombinacji typów, na które oba typy mogą być przekształcone. Jeśli kompilator znajdzie takie przeciążenie, użyje go. W przeciwnym razie, jeśli oba typy są typami referencyjnymi i nie są klasami niepowiązanymi (może to być interfejs lub mogą to być klasy pokrewne), kompilator uwzględni== jako operator porównania referencji. Jeśli żaden warunek nie zostanie spełniony, kompilacja się nie powiedzie.

Zauważ, że niektóre inne języki używają osobnych tokenów dla dwóch operatorów kontroli równości. Na przykład w VB.NET =token jest używany w wyrażeniach wyłącznie dla przeciążalnego operatora sprawdzania równości i Isjest używany jako test odniesienia lub operator testu zerowego. Zastosowanie =typu, który nie zastępuje operatora sprawdzania równości, zakończy się niepowodzeniem, podobnie jak próba użyciaIs w celu innym niż testowanie równości lub nieważności odniesienia.

(*) Typy zazwyczaj przeciążają równość tylko w celu porównania ze sobą, ale może być przydatne dla typów w celu przeciążenia operatora równości w celu porównania z innymi konkretnymi typami; na przykład intmógł (i IMHO powinien, ale nie zdefiniował) zdefiniować operatory równości do porównania float, tak aby 16777217 nie zgłosiłby się jako równy 16777216f. Ponieważ tak się nie dzieje, ponieważ żaden taki operator nie jest zdefiniowany, C # będzie promować intto float, zaokrąglając go do 16777216f, zanim operator kontroli równości zobaczy go; operator ten widzi następnie dwie równe liczby zmiennoprzecinkowe i zgłasza je jako równe, nieświadomy zaokrąglenia, które miało miejsce.


Zamiast mieć wartość false przy porównywaniu zmiennoprzecinkowym, wolę podejście stosowane przez F #, które w ogóle nie pozwala na takie porównanie. Następnie programista może zdecydować, czy i jak poradzić sobie z faktem, że wartości mają inny typ. Bo czasami, mimo wszystko, mamy zrobić chcesz traktować 3jako równe 3.0f. Jeśli wymagamy od programisty, aby powiedział, co jest zamierzone w każdym przypadku, nie ma niebezpieczeństwa domyślnego zachowania prowadzącego do niezamierzonych rezultatów, ponieważ nie ma domyślnego zachowania.
phoog

@ phoog: Osobiście uważam, że języki powinny mieć swoje „normalne” środki do testowania równości implementujące relację równoważności i zabraniające wszelkich kombinacji argumentów, dla których by tego nie zrobiły. Nie widzę wielkiej korzyści z równości sprawdzania języka między liczbami całkowitymi i zmiennoprzecinkowymi, potwierdzając, że zmiennoprzecinkowa dokładnie reprezentuje liczbę całkowitą pasującą do liczby całkowitej, w porównaniu z po prostu zabranianiem takich porównań, ale uznałbym, że którekolwiek z tych podejść byłoby lepsze niż wykonanie języka stratna konwersja przed porównaniem.
supercat

0

Naprawdę świetne odpowiedzi i przykłady!

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

Operatory takie jak ==nie są polimorficzne, podczas gdy Equalsjest

Mając na uwadze tę koncepcję, jeśli opracujesz dowolny przykład (patrząc na typ odniesienia lewej i prawej ręki oraz sprawdzając / wiedząc, czy typ rzeczywiście ma przeciążony operator == i jest zastępowany równy), na pewno otrzymasz właściwą odpowiedź .


-1

Kiedy tworzymy dowolny obiekt, mamy do czynienia z dwiema częściami, z których jedna stanowi treść, a druga jest odniesieniem do tej treści. ==porównuje zarówno treść, jak i referencje; equals()porównuje tylko treść

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


1
To nie jest prawda. Jeśli ai boba są odwołaniami do łańcucha, wynik a == bnie zależy od tego, czy odwołania wskazują na ten sam obiekt.
phoog

-2

==

Operator == może być użyty do porównania dwóch zmiennych dowolnego rodzaju i 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 tutaj nas to nie obchodzi.

int a (00000011) == bajt b (00000011)

Pamiętaj = = operator dba tylko o wzór bitów w zmiennej.

Użyj == Jeśli dwa odwołania (prymitywy) odnoszą się do tego samego obiektu na stercie.

Reguły są takie same, niezależnie od tego, czy zmienna jest odwołaniem, 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 jest fałszem

wzór bitowy jest taki sam dla a i c, więc są one równe przy użyciu ==.

Równy():

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

Takich jak dwa różne obiekty String, które reprezentują znaki w „Jane”


2
To jest niepoprawne. Zastanów się, co następuje: object a = 3; object b = 3; Console.WriteLine(a == b);. Dane wyjściowe są fałszywe, mimo że wzorce bitowe wartości są takie same. Liczą się także typy operandów. Powodem, dla którego „nie przejmujemy się” inną liczbą zer w twoim przykładzie jest to, że do czasu wywołania operatora równości liczba zer jest w rzeczywistości taka sama , z powodu niejawnej konwersji.
phoog

-2

Jedyna różnica między Equal i == polega na porównaniu typów obiektów. w innych przypadkach, takich jak typy referencyjne i typy wartości, są one prawie takie same (oba są równe bitowo lub oba są równe referencyjne).

obiekt: Równa się: równość bitowa ==: równość odniesienia

string: (równe i == są takie same dla ciągu, ale jeśli jeden z ciągów zostanie zmieniony na obiekt, wynik porównania będzie inny) Równa się: równość bitowa ==: równość bitowa

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


Object.Equals niekoniecznie patrzy na równość bitową. Jest to metoda wirtualna, a przesłonięcie może robić, co chce.
phoog

tak, masz rację, możesz zrobić, co chcesz, aby to zmienić. ale temat, o którym mówimy, jest domyślną implementacją. domyślną implementacją Object.Equals jest równość bitowa.
Czy Yu
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.