W wielu kontekstach, w których argument metody lub operatora nie jest wymaganego typu, kompilator C # będzie próbował przeprowadzić niejawną konwersję typu. Jeśli kompilator może sprawić, że wszystkie argumenty spełniają ich operatory i metody poprzez dodanie niejawnych konwersji, zrobi to bez zarzutu, nawet jeśli w niektórych przypadkach (szczególnie z testami równości!) Wyniki mogą być zaskakujące.
Ponadto, każdy typ wartości taki jak intlub shortfaktycznie opisuje zarówno rodzaj wartości, jak i rodzaj obiektu (*). Istnieją niejawne konwersje w celu konwersji wartości na inne rodzaje wartości oraz w celu konwersji dowolnego rodzaju wartości na odpowiadający mu rodzaj obiektu, ale różne rodzaje obiektów nie są wzajemnie konwertowalne.
Jeśli użyje się ==operatora do porównania a shorti an int, shortzostanie ono domyślnie przekonwertowane na an int. Jeśli jego wartość liczbowa była równa wartości, wartość int, na intktórą został przeliczony, będzie równa wartości, intz którą jest porównywany. Jeśli jednak spróbujemy użyć Equalsmetody w skrócie, aby porównać ją z intjedyną niejawną konwersją, która zaspokoi przeciążenie Equalsmetody, będzie konwersja na typ obiektu odpowiadający int. Kiedy shortzapyta się, czy pasuje do przekazanego obiektu, zauważy, że przedmiotowy przedmiot jest intraczej znakiem a niż shorta, co oznacza, że nie może być równy.
Ogólnie rzecz biorąc, chociaż kompilator nie będzie na to narzekać, należy unikać porównywania rzeczy, które nie są tego samego typu; jeśli ktoś jest zainteresowany tym, czy konwersja rzeczy do wspólnej formy dałaby ten sam wynik, należy taką konwersję wykonać jawnie. Zastanów się na przykład
int i = 16777217;
float f = 16777216.0f;
Console.WriteLine("{0}", i==f);
Istnieją trzy sposoby porównywania intz float. Można chcieć wiedzieć:
- Czy najbliższa możliwa
floatwartość intodpowiada wartości float?
- Czy część z liczbą całkowitą
floatpasuje do int?
- Wykonaj
inti floatreprezentuj tę samą wartość liczbową.
Jeśli ktoś próbuje porównać inti floatbezpośrednio, skompilowany kod będzie odpowiedzieć na pierwsze pytanie; czy tego właśnie zamierzał programista, nie będzie to jednak oczywiste. Zmiana porównania na (float)i == fwyjaśni, że pierwsze znaczenie było zamierzone, lub (double)i == (double)fspowoduje, że kod odpowie na trzecie pytanie (i wyjaśni, że to było zamierzone).
(*) Nawet jeśli specyfikacja C # traktuje wartość typu np. System.Int32Jako obiekt typu System.Int32, temu poglądowi zaprzecza wymóg, aby kod działał na platformie, której specyfikacja traktuje wartości i obiekty jako zamieszkujące różne wszechświaty. Ponadto, jeśli Tjest typem odniesienia, a xjest to T, to odniesienie typu Tpowinno być w stanie się odnosić x. Zatem, jeśli zmienna vtypu Int32zawiera an Object, odwołanie do typu Objectpowinno być w stanie pomieścić odwołanie do vlub jego zawartość. W rzeczywistości odniesienie typu Objectbyłoby w stanie wskazać obiekt zawierający dane skopiowane v, ale nie do vsiebie ani do jego zawartości. To by sugerowało, że żadne z nichvani jego zawartość nie jest tak naprawdę Object.