У багатьох контекстах, де аргумент методу чи оператора не є потрібним типом, компілятор C # спробує здійснити неявне перетворення типу. Якщо компілятор може змусити всі аргументи задовольнити своїх операторів та методи, додавши неявні перетворення, він зробить це без скарги, хоча в деяких випадках (особливо з тестами рівності!) Результати можуть бути дивовижними.
Крім того, кожен тип значення, такий як int
або short
фактично описує і вид значення, і вид об'єкта (*). Неявні перетворення існують для перетворення значень у інші види значень та для перетворення будь-якого виду значень у відповідний йому тип об'єкта, але різні види об'єктів неявно не перетворюються один в одного.
Якщо використовується ==
оператор для порівняння a short
і an int
, то short
буде неявно перетворено в an int
. Якщо його числове значення дорівнює значенню, то int
, int
до якого воно було перетворене, буде дорівнює тому, int
з яким воно порівнюється. Якщо спробувати використати Equals
метод на короткому, щоб порівняти його з int
, однак, єдиним неявним перетворенням, яке б задовольнило перевантаження Equals
методу, було б перетворення до відповідного типу об'єкта int
. Коли short
запитається питання, чи відповідає він об'єкту, що передається, він помітить, що відповідний об'єкт є int
скоріше аshort
а, і таким чином висновок, що він не може бути рівним.
Взагалі, хоча компілятор не буде скаржитися на це, слід уникати порівнювання речей, які не є одного типу; якщо когось цікавить, чи призведе перетворення речей у загальну форму однаковий результат, таку конверсію слід виконувати прямо. Розглянемо, наприклад,
int i = 16777217;
float f = 16777216.0f;
Console.WriteLine("{0}", i==f);
Існує три способи порівняння a int
з a float
. Можна було б знати:
- Чи відповідає найближче
float
значення до int
відповідностіfloat
?
- Чи відповідає цілочисленна частина
float
відповідностіint
?
- Зробіть
int
і float
представляйте однакове числове значення.
Якщо спробувати порівняти int
і float
безпосередньо, складений код відповість на перше запитання; чи це те, що планував програміст, буде далеко не очевидним. Змінивши порівняння на, (float)i == f
було б зрозуміло, що перше значення було призначене, або(double)i == (double)f
призведе до того, що код відповість на третє запитання (і дасть зрозуміти, що це було призначено).
(*) Навіть якщо специфікація C # розглядає значення типу, наприклад, System.Int32
як об'єкт типу System.Int32
, такий погляд суперечить вимозі, що код працює на платформі, специфікація якої розглядає значення та об'єкти як населені в різних всесвітах. Далі, якщо T
це посилальний тип і x
є a T
, тоді посилання типу T
повинно бути здатне посилатися x
. Таким чином, якщо змінна v
типу Int32
має значення Object
, посилання типу Object
повинна мати змогу містити посилання на v
його вміст. Фактично, посилання типу Object
могла б вказувати на об'єкт, що містить дані, скопійовані з v
, але не на v
себе, ані на його зміст. Це підказало б, що жоднеv
ні його зміст справді не є Object
.