2015-12-03 8 views
2

При поиске различных терминов «Спецификация языка C#, версия 5.0», похоже, нет явного утверждения о том, что LHS и RHS сравнения должны быть одного или того же типа или быть в явном виде конвертируемыми или через литье должно быть явно конвертируемым.Указывает ли спецификация языка C#, что сравнение должно быть одного типа?

Поисковые слова и фразы включают преобразование, литье, неявное, явное, если утверждение, и так далее.

Интуитивно, никто не сравнивает яблоки с апельсинами; независимо от того, неожиданно (для меня), AFAIK это явно не указано в спецификации языка C#.

+0

Можно определить пользовательские операторы сравнения, которые не используют одни и те же типы для обоих аргументов, поэтому я сомневаюсь, что существует явное ограничение. Все встроенные сравнения одного типа, и встроенные преобразования всегда доступны. –

+0

Возможно, вы спрашиваете о поведении встроенных операторов равенства, которые имеют следующее ограничение: «Ошибка привязки-времени использовать предопределенные операторы равенства ссылочного типа для сравнения двух ссылок, которые, как известно, различаются во время привязки. Например, если типы привязки-операнды являются двумя типами классов A и B, и если ни A, ни B не являются производными от другого, тогда было бы невозможно, чтобы оба операнда ссылались на один и тот же объект. Таким образом, операция считается ошибкой времени привязки ». –

ответ

3

Поскольку это допустимое сравнение, язык не запрещает его. В приведенном ниже примере нет никакого способа и не нужно преобразовывать A в B или наоборот, но код сравнения все еще действителен. Может быть, необоснованно логично, но верно компилятор.

class A { 
    public int a = 5; 

    public static bool operator==(A a, B b) { 
     return a.a == b.b; 
    } 
    public static bool operator!=(A a, B b) { 
     return !(a == b); 
    } 
} 
class B { 
    public int b = 5; 
} 
// ... 
Console.WriteLine(new A() == new B()); // "true" 
4

В спецификации нашли here, я нашел на странице 344 Котировка

Подпись бинарного оператора состоит из лексемы оператора (+, -, *, /,%, &, |, ^, < <, >>, ==,! =,>, <,> =, или < =) и типы двух формальных параметров.

Следует отметить, что «типы» являются плюрализованными. В C# я рассматриваю двоичные операторы как похожие на методы, которые принимают два параметра и возвращают значение данного типа. Тип возвращаемого значения должен определяться типами двух входных параметров.

UPDATE:

я решил добавить еще немного, так как я нахожу это интересным. В этом Eric Lippert Blog Post он говорит следующее.

[...] он является законным и удивительно общие для класса, чтобы реализовать == и Equals непоследовательно.

Все его сообщение в основном состоит в том, как C# определяет множество способов сравнения двух объектов, и нигде в спецификации не определено, что все они должны вести себя последовательно. Среди прочего, это означает, что вы можете определить свои собственные классы A и B так, чтобы (a as A) == (b as B) и (a as A) != (b as B) оценили одно и то же.

Это просто добавляет немного больше ударов позади моего комментария ранее, что бинарные операторы действительно очень похожи на методы в этом отношении. Язык C# не дает для них определенного значения, хотя мы, как люди, находим это запутанным.

5

Является ли спецификацией языка C# явно, что сравнение должно быть одного типа?

Нет. Операторы сравнения - < <= > >= == != - не должны иметь операндов того же типа с обеих сторон. Действительно, операнд не должен иметь тип. foo >= null совершенно легально, но null не имеет типа.

Интуитивно, никто не сравнивает яблоки с апельсинами; независимо от того, неожиданно (для меня), AFAIK это явно не указано в спецификации языка C#.

Есть ли интуитивное ожидание, чтобы иметь возможность сравнивать ints с шортами, шортами на десятичные знаки и так далее? Ожидается ли, что он сможет сопоставить NULL-ints с ints? Если менеджер - это своего рода человек, имеет ли смысл иметь возможность спросить: «Этот менеджер и этот человек одинаковы?» Я считаю, что очень интуитивно очевидно, что операнды оператора сравнения не должны быть одного и того же типа во время компиляции или во время выполнения.

+0

Хорошо, можно утверждать, что вы всегда * в конечном итоге сравниваете одни и те же типы. C# не применяет это в любом случае, но способ «IComparable» и * operator * реализуется во всей структуре, согласуется с этим поведением; 'IComparable.CompareTo (object obj)' выдает 'ArgumentException', когда аргумент не является типом вызываемого, а разрешение перегрузки просто терпит неудачу с операторами; 'int i = 1; ulong u = 1; var c = i> u; // оператор не может применяться к типам ... '. Дело в том, что оба аргумента должны быть легко трансформируемы в общий тип, который может выполнять сравнение. – InBetween

+2

@InBetween: Хотя я беру вашу точку зрения, вы, кажется, рассуждаете от конкретного к генералу. Тот факт, что никакой встроенный оператор сравнения C# не имеет операндов разных типов, - это просто факт истории языка, а не ограничение пространства дизайна. Если бы завтра команда дизайнеров хотела добавить оператора, который численно сравнивал бы улонг с длинными, он мог бы сделать это очень легко, не найдя тип больше, чем улонг и длинный. –

+0

Я согласен, поэтому я дал понять, что язык не обеспечивает этого. Я просто заявлял, что интуиция OP не такая уж надуманная, потому что рамка стоит и работает прямо сейчас, он в некотором смысле прав. – InBetween