2013-05-21 1 views
2

я натыкался этой интересной ситуацией сегодня:Почему целые числа не поднимаются до удвоений, когда рассматриваются как объекты и сравниваются?

var a = new HashSet<Object> { 1.0, 2.0, 3.0 }; 
a.Contains(1);  //False 
a.Contains(1.0); //True 

Конечно, это всего лишь общая версия этого:

Object b = 2.0; 
b.Equals(2);   //False 
b.Equals(2.0);   //True 

Я понимаю, что причина этого в том, что если я пишу 2.0 == 2, то Компилятор C# тайно вставляет листинг из целого числа в double, и с помощью промежуточного объекта Object у компилятора недостаточно информации для этого.

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

+1

JIT! = Время работы. Если вы хотите, чтобы эта работа работала, вы хотите понять ее во время выполнения, а не во время компиляции JIT. И если вы хотите, чтобы это «фигурировало» во время выполнения, есть слово для этого: динамическое. Используйте экономно. –

+0

Я бы порекомендовал это стать сообществом wiki, так как не обязательно существует конкретное решение, которое разрешает проблему. – galford13x

+0

@ user414076 Это не вопрос «почему мой код не работает». Это вопрос «почему они решили реализовать это таким образом». – MgSam

ответ

0

Это больше похоже на вопрос сообщества, а не на поиск конкретного решения. Но я буду рад весу.

Во-первых, я начну с того, что сравнение двойного равенства уже опасно, поскольку я уверен, что вы, возможно, знаете. Есть тонны информации там на тему

if(doubleNum == doubleNum2) 

, но и рассмотреть вопрос два объекта различных типов, которые не являются родственниками быть equatable? При написании кода компилятор может принять некоторые основные идеи. Но первое, что делают большинство методов .Equals (object), это проверка совместимости типов и если они несовместимы, возвращается false. Я бы предположил, что это имеет место здесь, поскольку b.Equals (2) предполагает, что передается int Type, который не является двойным.

Посмотрев на метод double.Equals (object), вы заметите, что первое, что он делает, это проверить, является ли переданный объект двойным. Из-за того, что он является Int32, функция возвращает false.

В то время как другие ответы больше касаются причин реализации. Вышеприведенное должно объяснить, почему время выполнения ведет себя так, как оно.

2

C# - специальный язык программирования со специфической семантикой для обработки 2.0 == 2, определенный в стандарте ECMA-334. Common Language Runtime (CLR) - это среда исполнения, определенная стандартом ECMA-335, и работает на байт-коде, а не на исходном коде C#. Семантика их отличается разными способами, поэтому, хотя часть времени исполнения может быть выполнена, для автоматического выполнения расширяющих преобразований для этих типов сравнений, то не был фактически выполнен таким образом.

Конкретное сравнение сделано здесь случается называть Double.Equals(Object), который возвращает

true если OBJ является экземпляром Double и равна значению данного экземпляра; в противном случае - false.

+0

Да, я спрашивал, есть ли причина, по которой это не было сделано. – MgSam

+0

Дополнительные проверки типов влияют на производительность во время выполнения, даже на код, где пользователю не нужна или нужна поддержка для подъема значений. Текущее определение обеспечивает минимальную поддержку, необходимую для сравнения значений «double», не прибегая к ненужным накладным расходам. –

4

C# должен работать так, как указано в спецификации языка, что он работает. Это не имеет ничего общего с Jitter, который просто должен реализовать спецификацию языка.

Спецификация языка C# говорит, как должен работать ==.

В спецификации CLR указано, как должен работать Equals().

Было действительно интересное изменение между .Net 1.1 и .Net 2.0.

В .Net 1.1, 3f.Equals(3) == false.

В .Net 2.0, 3f.Equals(3) == true.

Это не так же, как и объекта сравнения версии Equals(). Показывает, насколько это тонкое явление.

Интересный (но очень старый) блог об этом здесь: http://blogs.msdn.com/b/jmstall/archive/2005/03/23/401038.aspx

Это на самом деле есть несколько деталей, которые имеют отношение к вашему вопросу, так что стоит читать.

+0

Я считаю несчастливым, что метод «Object» использует то же имя, что и методы эквивалентных типов, поскольку первый должен определять отношение эквивалентности, но существование последнего означает, что не существует типа 'T', в которое расширяются преобразования существует очень хорошо, что для всех 'X' типа' T' и 'Y' произвольного типа' X.Equals (Y) 'будет соответствовать' Y.Equals (X) '. – supercat

Смежные вопросы