1

当我发现我 在旅行 时调用GetHashCode()了类的覆盖方法时,我感到很惊讶。但在其他情况下不会发生。为什么?FooforeachIEnumerable<Foo>

真实代码的一些部分:

var allVolumeImagesInvolvedInMerge = volumeChainsToMerge
    .SelectMany(x => x);

var allVolumeImagesNotInvolvedInMerge = allVolumeImagesWithinCell
    .Except(allVolumeImagesInvolvedInMerge)
    .Where(vi => volumeImagesNotAllowedToDelete.ContainsFast(vi) == false);

var volumeImagesCandidatesForDeletion = allVolumeImagesNotInvolvedInMerge
    .Where(x => driverVolumeIds.Contains(x.DriverVolumeId));

var groupedVolumeImagesCandidatesForDeletion = volumeImagesCandidatesForDeletion
    .GroupBy(vi => vi.DriverVolumeId);

// here GetHashCode is called
foreach (var group in groupedVolumeImagesCandidatesForDeletion)
{
   ...
}
4

1 回答 1

7

我假设你IEnumerable<Foo>的不是一个集合类型Foo[]List<Foo>而是一个使用延迟执行的 linq 查询。因此,当您使用foreach(或ToListAny)时,您将执行导致所有相关方法执行的查询。

也许您正在使用GroupBy, Distinct, Intersect,ExceptJoin其他使用覆盖的方法GetHashCodeEquals(如果GetHashCode返回相等的值)。

这是一个重现它的简单示例:

public class Foo
{
    public int ID { get; set; }

    public override int GetHashCode()
    {
        return ID.GetHashCode();
    }
    public override bool Equals(object obj)
    {
        Foo f2 = obj as Foo;
        if (f2 == null) return false;
        return ID == f2.ID;
    }
}

现在这个简单的 linq 查询演示GetHashCodeforeach由于Enumerable扩展方法的延迟执行而执行的:

IEnumerable<Foo> list1 = new List<Foo>() { new Foo { ID = 1 }, new Foo { ID = 2 }, new Foo { ID = 3 } };
IEnumerable<Foo> list2 = new List<Foo>() { new Foo { ID = 2 }, new Foo { ID = 3}, new Foo { ID = 4 } };
IEnumerable<Foo> inBoth = list1.Intersect(list2);

// now GetHashCode will be executed (not at list1.Intersect(list2))
foreach (Foo fDup in inBoth)
    Console.WriteLine(fDup.ID);

这是一个演示:http: //ideone.com/ekttH3

输出:

before Intersect
after Intersect
in GetHashCode, ID=2
in GetHashCode, ID=3
in GetHashCode, ID=4
in GetHashCode, ID=1
in GetHashCode, ID=2
in Equals, ID=2
in foreach, ID=2
in GetHashCode, ID=3
in Equals, ID=3
in foreach, ID=3
于 2013-04-03T13:57:33.057 回答