C# IEnumerable未在foreach中枚举

C# IEnumerable未在foreach中枚举,c#,.net,.net-4.0,ienumerable,C#,.net,.net 4.0,Ienumerable,我的一个IEnumerable遇到了一个以前从未见过的问题 我有一个收藏: IEnumerable<IDependency> dependencies; 出于某种原因,此foreach不会在myIEnumerable上迭代,而是直接跳到末尾 如果我将我的foreach更改为循环浏览a列表,但它似乎工作正常: foreach (var dependency in dependencies.ToList()) 我会做什么导致这种行为?我以前从未在IEnumerable中遇到过这种情况

我的一个
IEnumerable
遇到了一个以前从未见过的问题

我有一个收藏:

IEnumerable<IDependency> dependencies;
出于某种原因,此
foreach
不会在my
IEnumerable
上迭代,而是直接跳到末尾

如果我将我的
foreach
更改为循环浏览a列表,但它似乎工作正常:

foreach (var dependency in dependencies.ToList())
我会做什么导致这种行为?我以前从未在
IEnumerable
中遇到过这种情况

更新

下面是我的
foreach
方法中运行的整个代码
GenerateDotString

foreach (var dependency in dependencies)
{
    var dependentResource = dependency.Resource;
    var lineColor = (dependency.Type == DependencyTypeEnum.DependencyType.Hard) ? "blue" : "red";

    output += labelFormat.FormatWith(dependentResource.Name.MakeDotsafeString(), dependentResource.Name, dependentResource.ResourceType);
    output += relationshipFormat.FormatWith(dependentResource.Name.MakeDotsafeString(), currentName, lineColor);

    if (dependentResource.DependentResources != null)
    {
        output += GenerateDotString(dependentResource, dependentResource.DependentResources, searchDirection);
    }
}

return output;
更新2

下面是包含此foreach的方法的签名(如果有帮助的话)

更新4

我在这里添加了链中的方法,以明确我们是如何获得依赖项集合的

上述方法
GetAllRelatedResourcesByParentGuidWithoutCacheCheck
接受一个委托,在本例中,该委托是:

private IEnumerable<IDependency> GetAllSupportsResources(Guid resourceId)
{
    var hardDependents = GetSupportsHardByParentGuid(resourceId);
    var softDependents = GetSupportsSoftByParentGuid(resourceId);
    var allresources = hardDependents.Union(softDependents);
    return allresources;
}
private IEnumerable GetAllSupportsResources(Guid resourceId)
{
var hardDependents=GetSupportsHardByParentGuid(resourceId);
var softDependents=GetSupportsSoftByParentGuid(resourceId);
var allresources=hardDependents.Union(softDependents);
归还所有资源;
}
正在呼叫:

private IEnumerable<IDependency> GetSupportsHardByParentGuid(Guid parentCiGuid)
{
    XmlNode ciXmlNode = _reportManagementService.RunReportWithParameters(Res.SupportsHardReportGuid, Res.DependentCiReportCiParamName + "=" + parentCiGuid);
    return GetResourcesFromXmlNode(ciXmlNode, DependencyTypeEnum.DependencyType.Hard);
}
private IEnumerable GetSupportsHardByParentGuid(Guid parentCiGuid)
{
XmlNode ciXmlNode=_reportManagementService.RunReportWithParameters(Res.SupportsHardReportGuid,Res.DependentCiReportCiParamName+“=”+parentCiGuid);
返回GetResourcesFromXmlNode(ciXmlNode,DependencyTypeEnum.DependencyType.Hard);
}
并返回:

private IEnumerable<IDependency> GetResourcesFromXmlNode(XmlNode ciXmlNode, DependencyTypeEnum.DependencyType dependencyType)
{
    var allResources = GetAllResources();

    foreach (var nodeItem in ciXmlNode.SelectNodes(Res.WebServiceXmlRootNode).Cast<XmlNode>())
    {
        Guid resourceGuid;
        var isValidGuid = Guid.TryParse(nodeItem.SelectSingleNode("ResourceGuid").InnerText, out resourceGuid);

        var copyOfResource = allResources.Where(m => m.Id == resourceGuid).SingleOrDefault();
        if (isValidGuid && copyOfResource != null)
        {
            yield return new Dependency
            {
                Resource = copyOfResource,
                Type = dependencyType
            };
        }
    }
}
private IEnumerable GetResourcesFromXmlNode(XmlNode ciXmlNode,DependencyTypeEnum.DependencyType DependencyType)
{
var allResources=GetAllResources();
foreach(ciXmlNode.SelectNodes(Res.WebServiceXmlRootNode.Cast()中的var nodeItem)
{
Guid资源Guid;
var isValidGuid=Guid.TryParse(nodeItem.SelectSingleNode(“ResourceGuid”).InnerText,out ResourceGuid);
var copyOfResource=allResources.Where(m=>m.Id==resourceGuid.SingleOrDefault();
if(isValidGuid&©OfResource!=null)
{
返回新的依赖项
{
资源=资源的副本,
类型=依赖类型
};
}
}
}

这就是返回具体类型的地方。

因此,问题似乎与
依赖项有关,这取决于它本身

从我的调试中可以看出,迭代
IEnumerable
会导致超时,因此
foreach
会跳过其内容的执行,其中as
ToList()
会在超时之前返回尽可能多的内容

关于这一点我可能不正确,但据我所知,情况似乎是这样的

为了让大家了解一下这一切是如何发生的,我将解释我昨天所做的代码更改

应用程序要做的第一件事是建立一个按资源类型筛选的所有资源的集合。这些是通过web服务调用从CMDB引入的

然后,我所做的是对所选择的每个资源(在本例中通过autocomplete)进行web服务调用,并根据其Guid获取资源的依赖项。(递归地)

我昨天更改了这个,这样我们就不需要在第二次web服务调用中获取完整的资源信息,而只需要在web服务调用中获取一个GUID列表,并从我们的资源集合中获取资源

我忘记的是,对依赖项的web服务调用没有按类型过滤,因此它返回的结果在原始资源集合中不存在

我需要看得更远一点,但在这一点上,新的依赖资源集合似乎变得依赖于自身,从而导致
IEnumerable
集合稍后超时

这就是我今天要去的地方,如果我还发现什么,我一定会记在这里

总结如下:

如果在IEnumerable中发生无限递归,它只会超时 尝试在foreach中枚举时

在IEnumerable上使用ToList()似乎可以返回与其相同的数据量 在超时之前,您可以重新启动


它取决于循环的内容和
IEnumerable
。依赖项包含31个更确切的IDependency,依赖项的确切类型是什么以及如何访问它?好的。。。也许我的措辞很糟糕。
依赖项
引用的对象必须是具体类型的实例(如
列表
IDependency[]
),而不是接口。我们需要知道具体类型是什么。可能是在您实际执行枚举时,某些设置(请记住,这是惰性计算的)不再有效吗?例如,您传递给它的委托在您启动枚举时是否仍能完成其工作?
IEnumerable
本身不会超时。如果存在无限递归,它(很可能)会抛出
StackOverflowException
。可能所有资源都会超时,这取决于如何实现。
private IEnumerable<IDependency> GetAllSupportsResources(Guid resourceId)
{
    var hardDependents = GetSupportsHardByParentGuid(resourceId);
    var softDependents = GetSupportsSoftByParentGuid(resourceId);
    var allresources = hardDependents.Union(softDependents);
    return allresources;
}
private IEnumerable<IDependency> GetSupportsHardByParentGuid(Guid parentCiGuid)
{
    XmlNode ciXmlNode = _reportManagementService.RunReportWithParameters(Res.SupportsHardReportGuid, Res.DependentCiReportCiParamName + "=" + parentCiGuid);
    return GetResourcesFromXmlNode(ciXmlNode, DependencyTypeEnum.DependencyType.Hard);
}
private IEnumerable<IDependency> GetResourcesFromXmlNode(XmlNode ciXmlNode, DependencyTypeEnum.DependencyType dependencyType)
{
    var allResources = GetAllResources();

    foreach (var nodeItem in ciXmlNode.SelectNodes(Res.WebServiceXmlRootNode).Cast<XmlNode>())
    {
        Guid resourceGuid;
        var isValidGuid = Guid.TryParse(nodeItem.SelectSingleNode("ResourceGuid").InnerText, out resourceGuid);

        var copyOfResource = allResources.Where(m => m.Id == resourceGuid).SingleOrDefault();
        if (isValidGuid && copyOfResource != null)
        {
            yield return new Dependency
            {
                Resource = copyOfResource,
                Type = dependencyType
            };
        }
    }
}