使用IEnumerable而不使用foreach循环

时间:2010-02-12 01:07:16

标签: c# ienumerable yield-return

我必须在这里找到一些简单的东西。

请使用以下代码:

public IEnumerable<int> getInt(){
  for(int i = 0; i < 10; i++){
   yield return i;
  }
}

我可以这样称呼:

foreach (int j in obj.getInt()){
  //do something with j
}

如何在没有foreach循环的情况下使用getInt方法:

IEnumerable<int> iter = obj.getInt();
// do something with iter ??

感谢。

EDITS

对于那些想知道为什么我想要这个的人。我正在迭代两件事:

IEnumerator<int> iter = obj.getInt().GetEnumerator();
foreach(object x in xs){
  if (x.someCondition) continue;
  iter.MoveNext();
  int n = iter.current();
  x.someProp = n;
  etc...
}

7 个答案:

答案 0 :(得分:58)

您可以使用GetEnumerator方法获取对Enumerator的引用,然后您可以使用MoveNext()方法继续前进,并使用Current属性访问你的元素:

var enumerator = getInt().GetEnumerator();
while(enumerator.MoveNext())
{
    int n = enumerator.Current;
    Console.WriteLine(n);
}

答案 1 :(得分:31)

我的建议:不要乱搞普查员。将您的问题描述为序列上的一系列操作。编写代码来表达这些操作。让序列运算符负责管理枚举器。

那么让我们看看我是否已经这么做了。你有两个序列。让我们说{2,3,5,7,12}和{“青蛙”,“蟾蜍”}。你想要执行的逻辑操作是,“通过第一个序列。每次你找到一个可被3整除的数字,得到第二个序列中的下一个项目。用结果(数字,两栖)对做一些事情。”< / p>

轻松完成。首先,过滤第一个序列:

var filtered = firstSequence.Where(x=>x%3 == 0);

接下来,使用第二个序列压缩过滤后的序列:

var zipped = filtered.Zip(
             secondSequence, 
             (y, z)=> new {Number = x, Amphibian = y});

现在你可以遍历压缩序列并用这些对做任何你想做的事情:

foreach(var pair in zipped)
    Console.WriteLine("{0} : {1}", pair.Number, pair.Amphibian);

轻松自在,没有与普查员混淆。

答案 2 :(得分:4)

这个怎么样?

IEnumerator<int> iter = obj.getInt();
using(iter) {
    while(iter.MoveNext()) {
        DoSomethingWith(iter.Current)
    }
}

答案 3 :(得分:2)

使用for循环:

for (var enumerator = getInt().GetEnumerator(); enumerator.MoveNext(); )
{
    Console.WriteLine(enumerator.Current);
}

答案 4 :(得分:0)

虽然接受的答案是正确的,但请注意,在第一次调用MoveNext()之前,IEnumerator.Current未定义。

如果要迭代辅助数组,则需要以下内容:

IEnumerable<Foo> Foo() { ... }

int AssignValues(List<TakesFoo> data) {
  var count = 0;
  var foo = Foo().GetEnumerator();

  // Step into the first element of the array;
  // doing this does not discard a value from the IEnumerator
  if (foo.MoveNext()) { 
    foreach (var x in data) {
      x.SetFoo(foo.Current);
      count += 1;
      if (!foo.MoveNext()) { 
        break;
      }
   }

   // Return count of assigned values
   return count;
}

答案 5 :(得分:0)

重要的是要提到foreach循环的职责是在实例实现IDisposable时处置枚举器。换句话说,foreach应该替换为:

var enumerator = enumerable.GetEnumerator();

try
{
    while (enumerator.MoveNext())
    {
        var item = enumerator.Current;
        // do stuff
    }
}
finally
{
    var disposable = enumerator as IDisposable;
    if (disposable != null)
    {
        disposable.Dispose();
    }
}

答案 6 :(得分:0)

样品

public static void SampleIteratorNext()
{
    var beauty = BeautifulLadies().GetEnumerator();

    Console.WriteLine($"Friday with {Next(beauty)} ...");
    Console.WriteLine($"Saturday with {Next(beauty)} ...");
    Console.WriteLine($"Tusday with {Next(beauty)} ...");
}

public static IEnumerable<string> BeautifulLadies()
{
    yield return "Scarlett";
    yield return "Alexandra";
    yield return "Alisson";
}

// emulate next() in python
public static T Next<T>(IEnumerator<T> iterator)
{
    iterator.MoveNext();
    return iterator.Current;
}