Mam dwa obiekty w C # i nie wiem, czy jest to typ Boolean, czy inny. Jednak gdy próbuję porównać te C # nie daje poprawnej odpowiedzi. Wypróbowałem ten sam kod z VB.NET i to się udało!
Czy ktoś może mi powiedzieć, jak to naprawić, jeśli istnieje rozwiązanie?
DO#:
object a = true;
object b = true;
object c = false;
if (a == b) c = true;
MessageBox.Show(c.ToString()); //Outputs False !!
VB.NET:
Dim a As Object = True
Dim b As Object = True
Dim c As Object = False
If (a = b) Then c = True
MessageBox.Show(c.ToString()) '// Outputs True
c#
.net
vb.net
comparison
Mohsen Sarkar
źródło
źródło
a.Equals(b)
?a
siebie otrzymujesz boks i utworzysz pudełko zawierającetrue
. Kiedy przypisujesz dob
siebie, otrzymasz kolejne pudełko zawierające równieżtrue
. Podczas porównywaniaa
ib
, ponieważ oba są typu czasu kompilacjiobject
, wywołujesz przeciążenieoperator ==(object, object)
zdefiniowane przez specyfikację języka C #. To przeciążenie sprawdza, czy odwołania przechodzą do tego samego obiektu. Ponieważ masz dwa pola, wynikiem jestfalse
, a stwierdzenie „pod”if
nie będzie działać. Aby lepiej to zrozumieć, spróbuj zmienić przypisanieb
do tego:object b = a;
Teraz masz tylko jedno pudełko.Odpowiedzi:
W języku C #
==
operator (w przypadku zastosowania do wyrażeń typu referencyjnego) wykonuje sprawdzenie równości odwołań, chyba że jest przeciążony . Porównujesz dwa odniesienia, które są wynikiem konwersji bokserskich, więc są to różne odniesienia.EDYCJA: W przypadku typów, które przeciążają
==
, możesz uzyskać inne zachowanie - ale jest to oparte na typie wyrażeń w czasie kompilacji . Na przykładstring
zapewnia==(string, string
):Tutaj pierwsze porównanie używa przeciążonego operatora, ale drugie używa „domyślnego” porównania referencji.
W VB
=
operator wykonuje o wiele więcej pracy - nie jest to nawet równoważne użyciuobject.Equals(x, y)
, ponieważ takie rzeczyOption Compare
mogą wpływać na sposób porównywania tekstu.Zasadniczo operatory nie działają w ten sam sposób i nie mają działać w ten sam sposób.
źródło
=
zrobiłem w VB, ale specyfikacja nie jest zbyt jasna.bool == bool
porównanie.Oprócz odpowiedzi Jona, która wyjaśnia stronę C #, oto co robi VB:
W VB z
Option Strict On
, porównanie poprzez=
zawsze sprawdza równość wartości, a nigdy równość odniesienia. W rzeczywistości Twój kod nawet się nie kompiluje po przełączeniu,Option Strict On
ponieważSystem.Object
nie definiuje plikuOperator=
. Powinieneś zawsze mieć tę opcję włączoną, łapie ona owady skuteczniej niż muchołówka (chociaż w twoim konkretnym przypadku to luźne zachowanie działa właściwie). 1W rzeczywistości, z
Option Strict On
VB zachowuje się jeszcze bardziej rygorystyczne niż C # w C #,a == b
albo wyzwala wywołanieSomeType.operator==(a, b)
lub, jeśli nie istnieje, powołuje porównania równości odniesienia (co jest równoznaczne z wywołaniemobject.ReferenceEquals(a, b)
).Z drugiej strony w języku VB porównanie
a = b
zawsze wywołuje operator równości. 2 Jeśli chcesz użyć porównania równości odniesień, musisz użyća Is b
(co znowu jest tym samym coObject.ReferenceEquals(a, b)
).1) Oto dobra wskazówka, dlaczego używanie
Option Strict Off
jest złym pomysłem: korzystałem z VB.NET przez prawie dekadę, od oficjalnego wydania .NET aż do kilku lat temu i nie mam pojęcia, coa = b
się z nim dziejeOption Strict Off
. Robi jakieś porównanie równości, ale co dokładnie się dzieje i dlaczego, nie mam pojęcia. Jest to jednak bardziej złożone niżdynamic
funkcja C # (ponieważ opiera się na dobrze udokumentowanym interfejsie API). Oto, co mówi MSDN:2) Jon wspomniał o jednym wyjątku, łańcuchach, gdzie porównanie równości robi więcej rzeczy ze względu na kompatybilność wsteczną.
źródło
Option Strict On
musi być uznane za przestępstwo ...Instancje obiektów nie są porównywane z operatorem „==”. Powinieneś użyć metody „równa się”. Za pomocą operatora „==” porównujemy referencje, a nie obiekty.
Spróbuj tego:
Wyniki:
Teraz spróbuj tego:
Wyniki:
źródło
operator ==
. Jeśli przesłonisz ten operator i nie jest równy, to wynik zostanie odwrócony. Nie ma nic nieodłącznego w porównywaniu odniesieniaoperator ==
ani nic nieodłącznego w porównywaniu wartości wEquals
. To tylko dwa sposoby określania równości; oba mają domyślne implementacje porównania referencji i można je przesłonić, aby zrobiły to, co chcesz. Jedyną różnicą jest to, żeEquals
jest wirtualny, aoperator ==
nie.==
- możesz go tylko przeciążać .Problem polega na tym, że operator == w C # jest wywołaniem metody statycznej (no może nie technicznie, ale może być tak pomyślana) na podstawie typu czasu kompilacji dwóch parametrów. Nie ma znaczenia, jakie są rzeczywiste typy środowiska uruchomieniowego tych obiektów.
Na podstawie tego typu czasu kompilacji kompilator określi, której implementacji
operator ==
użyć. Może używać domyślnejobject
implementacji, może używać jednego z przeciążeń numerycznych dostarczonych przez język lub może to być implementacja zdefiniowana przez użytkownika.Różni się to od VB tym, że VB nie określa implementacji w czasie kompilacji. Czeka do czasu wykonania i sprawdza dwa parametry, które otrzymuje, aby określić, której implementacji
==
operatora powinien użyć.Twój kod zawiera wartości logiczne, ale są one w zmiennych typu
object
. Ponieważ zmienna jest typuobject
, kompilator C # używaobject
implementacji==
, która porównuje odwołania , a nie wystąpienia obiektów. Ponieważ wartości logiczne to pola, nie mają tego samego odniesienia, mimo że ich wartości są takie same.Kod VB nie dba o typ zmiennej. Czeka do czasu uruchomienia, a następnie sprawdza dwie zmienne, widzi, że obie są w rzeczywistości typu boolowskiego, więc używa
==
implementacji operatora boolowskiego . Ta implementacja porównuje wartości parametrów logicznych, a nie ich referencji (a wartości logiczne zostaną rozpakowane przed wywołaniem tego operatora, więc porównanie referencji nie ma już nawet sensu). Ponieważ wartości logiczne są takie same, zwraca prawdę.źródło
=
robi w VB, żeby na pewno powiedzieć.=
razem ze wszystkimi innymi relacyjnych operatorów porównania, takich jak<
,>=
itp , są traktowane w specjalny sposób, gdy obie strony lub obie strony są traktowaneObject
. To specjalne traktowanie jest wykonywane po to, aby programiści VB6, którzy są przyzwyczajeni do używania typu znanego jakoVariant
pre-.NET VB, mogą korzystać zObject
VB.Net w sposób, w jaki używali goVariant
wcześniej.Option Strict On
, VB=
jest nastawiony na rozpakowywanie an,Object
dopóki nie dotrze do łańcucha lub wartości liczbowej.