当我使用GetHashCode()
在Foo
中旅行时,我发现我的覆盖foreach
类IEnumerable<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)
{
...
}
答案 0 :(得分:7)
我假设您的IEnumerable<Foo>
不是像Foo[]
或List<Foo>
这样的集合类型,而是使用延迟执行的linq查询。因此,当您使用foreach
(或ToList
,Any
等)时,您将执行查询,从而导致执行所有相关方法。
也许您正在使用GroupBy
,Distinct
,Intersect
,Except
,Join
或其他使用被覆盖的GetHashCode
和{的方法{1}}(如果Equals
返回相等的值)。
这是一个重现它的简单例子:
GetHashCode
现在,这个简单的linq查询表明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;
}
}
由于GetHashCode
扩展方法的延迟执行而在foreach
中执行:
Enumerable
以下是演示:http://ideone.com/ekttH3
输出:
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);