我对foreach循环有一些奇怪的行为:
IEnumerable<Compound> loadedCompounds;
...
// Loop through the peaks.
foreach (GCPeak p in peaks)
{
// Loop through the compounds.
foreach (Compound c in loadedCompounds)
{
if (c.IsInRange(p) && c.SignalType == p.SignalType)
{
c.AddPeak(p);
}
}
}
所以我想做的事情:遍历所有GCPeaks(它是一个类)并将它们分类为相应的化合物。
AddPeak只是将GCPeak添加到SortedList。代码编译和运行没有例外,但问题是:
在c.AddPeak(p)之后,c中的SortedList包含GCPeak(使用Debugger检查),,而loadedCompounds中的SortedLists保持为空。
我对我制作的这个错误非常困惑:
修改
这就是我获取IEnumarables的方式(整个过程来自XML文件 - LINQ to XML)。化合物基本上以相同的方式获得。
IEnumerable<GCPeak> peaksFromSignal = from p in signal.Descendants("IntegrationResults")
select new GCPeak()
{
SignalType = signaltype,
RunInformation = runInformation,
RetentionTime = XmlConvert.ToDouble(p.Element("RetTime").Value),
PeakArea = XmlConvert.ToDouble(p.Element("Area").Value),
};
谢谢!
答案 0 :(得分:0)
IEnumerable赢得了对您的列表的硬引用。这会给您带来两个潜在的问题。
1)你所枚举的内容可能不再存在(例如,如果你使用惰性技术(如IEnumerable等)枚举facebook帖子列表,但是你关于facebook的连接已关闭,那么它可能会评估为空如果您在数据库集合上执行IEnumerable但该数据库连接已关闭等,则会发生同样的情况。
2)使用类似的枚举可能会导致您稍后或之前执行多重枚举,这可能会产生问题。 Resharper通常会对此发出警告(以防止出现意外后果)。有关详细信息,请参阅此处:Handling warning for possible multiple enumeration of IEnumerable
你可以做的调试你的情况是使用.toList()的LINQ扩展来强制早期评估你的IEnumerable。这将让您更容易地看到IEnumerable中的内容,并允许您通过代码执行此操作。请注意,与当前的惰性引用相比,执行toList()确实会产生性能影响,但它会提前强制引用硬件并帮助您调试场景,并避免上述情况给您带来挑战。
答案 1 :(得分:0)
感谢您的评论。
确实将我加载的化合物转换为List&lt;&gt;工作。
获得的经验教训:小心IEnumerable。
修改强> 根据要求,我正在添加AddPeak的实现:
public void AddPeak(GCPeak peak)
{
if (peak != null)
{
peaks.Add(peak.RunInformation.InjectionDateTime, peak);
}
}
RunInformation是一个结构。