如何第二次枚举 IEnumerable?

Sco*_*ott 2 c# ienumerable foreach

我有以下内容:

IEnumerable<string> lines // passed into method

foreach (var data in lines.ParseAsEnumberable(Delimiter, StringQualifer))
{
...
}
Run Code Online (Sandbox Code Playgroud)

foreach这对于这个特定的循环来说很好。但我想再经历一次lines 但得到一个

“可能的多重枚举”

如果我再次使用类似的循环,就会发出警告,果然,第二次就没有枚举结果了。

我该如何度过lines第二次?

编辑添加:我的老板通知我我们不应该使用 ToList,因为我们有包含许多 GB 数据的文件。我可以用什么来代替?

Dmi*_*nko 6

问题IEnumerable<T>在于一般情况下它是不一致的,例如当我们从外部源(如文件、RDBMS 表、COM 端口等)读取数据时

IEnumerable<string> lines = File
  .ReadLines(@"c:\...")
  ...
Run Code Online (Sandbox Code Playgroud)

当我们第二次枚举时,我们可以得到不同的lines数据(文件、表可以更改)。为了避免这种可能的不一致,您可以具体化枚举:

// Materialization can be required, but 
// let's avoid overhead if lines is already a collection.
// From now on source is a collection; it doesn't change between loops
var source = lines as IReadOnlyCollection<string> ?? lines.ToList();

...

// 1st loop
foreach(var data in source.ParseAsEnumberable(Delimiter, StringQualifer)) {
  ...
}

...

// 2nd loop over the very same collection
foreach(var item in source) {
  ...
}
Run Code Online (Sandbox Code Playgroud)

编辑:如果您绝对确定必须多次循环枚举并且不会出现不一致问题,则可以借助以下方法抑制pragma警告:

//TODO: Provide justification why it is safe to break the rule here
// E.g. "The file is locked and can't be modified"
#pragma warning disable CA1851

foreach (var data in lines.ParseAsEnumberable(Delimiter, StringQualifer)) {
  ...
}

...

foreach (var item in lines) {
  ...
}

// Don't forget to restore: 
// we've adjusted just one exception from the general rule 
#pragma warning restore CA1851
Run Code Online (Sandbox Code Playgroud)