“==”运算符的行为与编译器生成的匿名类型的 Equals() 重写不同

问题描述 投票:0回答:2

根据MSDN

因为Equals和GetHashCode 定义了匿名类型的方法 就 Equals 和 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));
}
c# .net anonymous-types
2个回答
7
投票

==
不是
Equals()
- 我相信当您这样做时,您的代码应该按预期工作:

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

另请参阅这个问题


6
投票

Lucero 说得对,但我想添加一个解释为什么这是对的。

对于 .Net 中的引用类型,== 运算符旨在指示 reference 相等;两个变量是否引用一个对象的完全相同的实例?

另一方面,.Equals() 方法旨在指示

value 相等;对于通常允许为您的类型提供的“相同”的某些定义,对象的两个(可能)不同实例是否具有相同的值?

© www.soinside.com 2019 - 2024. All rights reserved.