Оператор "==" не ведет себя так, как сгенерированное компилятором переопределение Equals () для анонимного типа - PullRequest
8 голосов
/ 21 февраля 2010

Согласно MSDN :

Потому что Equals и GetHashCode методы на анонимных типах определены с точки зрения равных и GetHashcode свойств, два экземпляра равны только один и тот же анонимный тип если все их свойства равны.

Однако следующий код демонстрирует, что реализация, сгенерированная компилятором для Equals(), не работает должным образом

 DateTime start = new DateTime(2009,1,1);
 DateTime end = new DateTime(2010, 12,31);

 // months since year 0
 int startMonth = start.Date.Year * 12 + start.Date.Month - 1;
 int endMonth = end.Date.Year * 12 + end.Date.Month -1 ;

 // iterate through month-year pairs
 for (int i = startMonth; i <= endMonth ; i++)
 {
  var yearMonth = new { Year = (int)Math.Truncate(i/12d), Month = (i % 12) + 1};

  if (yearMonth.Year == 2009 &&  yearMonth.Month == 2)
   Console.WriteLine("BOOM");

  if (yearMonth == new{Year = 2009, Month = 2})
   Console.WriteLine("I'm never called!");

  Console.WriteLine(yearMonth);
 }

Я что-то упустил? Я смотрю на сгенерированный MSIL, но не вижу очевидной ошибки. Есть ли способ отладки на уровне MSIL (кроме WinDbg, может быть)? Я что-то пропускаю?

Я тестировал .NET 3.5 (компилятор VS 2008 SP1). Для справки вот сгенерированный метод Equals:

public override bool Equals(object value)
{
    var type = value as <>f__AnonymousType3<<Year>j__TPar, <Month>j__TPar>;
    return (((type != null) && EqualityComparer<<Year>j__TPar>.Default.Equals(this.<Year>i__Field, type.<Year>i__Field)) && EqualityComparer<<Month>j__TPar>.Default.Equals(this.<Month>i__Field, type.<Month>i__Field));
}

Ответы [ 2 ]

7 голосов
/ 21 февраля 2010

== не Equals() - я полагаю, что ваш код должен работать так, как ожидалось, когда вы делаете это:

if (yearMonth.Equals(new{Year = 2009, Month = 2}))

См. Также этот ТАК вопрос .

6 голосов
/ 21 февраля 2010

У Lucero все правильно, но я хочу добавить объяснение , почему верно.

Для ссылочных типов в .Net оператор == предназначен для указания равенства reference ; две переменные ссылаются на один и тот же экземпляр объекта?

Метод .Equals (), с другой стороны, предназначен для указания значения равенства; два (возможно) разных экземпляра объекта имеют одно и то же значение для некоторого определения "то же самое", которое вам обычно разрешено предоставлять для ваших типов?

...