У багатьох контекстах, де аргумент методу чи оператора не є потрібним типом, компілятор 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.