Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么foreach调用GetHashCode?_C#_.net_Linq_Gethashcode - Fatal编程技术网

C# 为什么foreach调用GetHashCode?

C# 为什么foreach调用GetHashCode?,c#,.net,linq,gethashcode,C#,.net,Linq,Gethashcode,当我使用foreach在IEnumerable中旅行时,发现调用了Foo类的override GetHashCode方法时,我感到很惊讶。但在其他情况下不会发生这种情况。为什么? 真实代码的某些部分: var allVolumeImagesInvolvedInMerge = volumeChainsToMerge .SelectMany(x => x); var allVolumeImagesNotInvolvedInMerge = allVolumeImagesWithinCe

当我使用foreach在IEnumerable中旅行时,发现调用了Foo类的override GetHashCode方法时,我感到很惊讶。但在其他情况下不会发生这种情况。为什么?

真实代码的某些部分:

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)
{
   ...
}
我假设IEnumerable不是Foo[]或List这样的集合类型,而是使用延迟执行的linq查询。因此,当您使用foreach或ToList时,任何etc都将执行导致执行所有相关方法的查询

如果GetHashCode返回一个相等的值,那么您可能正在使用GroupBy、Distinct、Intersect、Except、Join或其他使用覆盖的GetHashCode和equals的方法

下面是一个简单的例子,它再现了这一点:

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查询演示了由于可枚举扩展方法的延迟执行,GetHashCode在foreach中执行:

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);
我假设IEnumerable不是Foo[]或List这样的集合类型,而是使用延迟执行的linq查询。因此,当您使用foreach或ToList时,任何etc都将执行导致执行所有相关方法的查询

如果GetHashCode返回一个相等的值,那么您可能正在使用GroupBy、Distinct、Intersect、Except、Join或其他使用覆盖的GetHashCode和equals的方法

下面是一个简单的例子,它再现了这一点:

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查询演示了由于可枚举扩展方法的延迟执行,GetHashCode在foreach中执行:

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);

发布您的循环和类在GetHashCode上放置一个断点,然后查看调用堆栈。我打赌IEnumerable涉及到我在reflector中看到的猜测是,IEnumerable正在抽象一个集合,因为它本身只是一个使用哈希代码的接口,可能用于MoveNext。如果显示示例代码,也许你可以得到一个更具体的答案。@EricLippert:或者他的IEnumerable正在包装一个字典或哈希表。发布你的循环,你的类在GetHashCode上放置一个断点,然后查看调用堆栈。我打赌IEnumerable涉及到我在reflector中的猜测,即IEnumerable正在抽象一个集合,因为它本身是只是一个使用散列代码的接口,可能用于MoveNext。如果您展示示例代码,也许您可以得到更具体的答案。@EricLippert:或者他的IEnumerable正在包装字典或哈希表。