返回一个空的IEnumerator

Dav*_*jak 54 c# ienumerator

我有一个接口,除其他外,实现了一个"公共IEnumerator GetEnumerator()"方法,所以我可以在foreach语句中使用该接口.

我在几个类中实现了这个接口,在其中一个类中,我想返回一个空的IEnumerator.现在我通过以下方式执行此操作:

public IEnumerator GetEnumerator()
{
    ArrayList arr = new ArrayList();
    return arr.GetEnumerator();
}
Run Code Online (Sandbox Code Playgroud)

但是我认为这是一个丑陋的黑客,我不禁认为有一个更好的方法来返回一个空的IEnumerator.在那儿?

Jon*_*eet 80

这在C#2中很简单:

public IEnumerator GetEnumerator()
{
    yield break;
}
Run Code Online (Sandbox Code Playgroud)

您需要该yield break语句强制编译器将其视为迭代器块.

这将比"自定义"空迭代器效率低,但它的代码更简单......

  • @Konamiman:完全没有.还记得你回答然后删除的LINQ问题,发现属性的值是必需的吗?我错过了! (11认同)
  • 在C#问题中尝试与你竞争是毫无意义的.:-) (4认同)

use*_*107 78

框架中有一个额外的功能:

public static class Enumerable
{
    public static IEnumerable<TResult> Empty<TResult>();
}
Run Code Online (Sandbox Code Playgroud)

使用这个你可以写:

var emptyEnumerable = Enumerable.Empty<int>();
var emptyEnumerator = Enumerable.Empty<int>().GetEnumerator();
Run Code Online (Sandbox Code Playgroud)

  • 获取IEnumerator <T>而不是IEnumerable <T>:Enumerable.Empty <Whatever>().GetEnumerator(); (12认同)

Kon*_*man 12

您可以实现一个实现IEnumerator的虚拟类,并返回它的实例:

class DummyEnumerator : IEnumerator
{
    public object Current
    {
        get
        {
            throw new InvalidOperationException();
        }
    }

    public bool MoveNext()
    {
        return false;
    }

    public void Reset()
    {
    }
}
Run Code Online (Sandbox Code Playgroud)


San*_*hos 7

我很好奇,走得更远。我做了一个测试,检查,如何有效的方法比较yield breakEnumerable.Emtpy和自定义类。

您可以在dotnetfiddle https://dotnetfiddle.net/vTkmcQ上查看它,或使用下面的代码。

使用190 000次迭代的许多dotnetfiddle运行之一的结果是:

屈服点:00:00:00.0210611

Enumerable.Empty():00:00:00.0192563

EmptyEnumerator实例:00:00:00.0012966

using System;
using System.Diagnostics;
using System.Collections;
using System.Linq;

public class Program
{
    private const int Iterations = 190000;
    public static void Main()
    {
        var sw = new Stopwatch();

        sw.Start();
        for (int i = 0; i < Iterations; i++)
        {
            IEnumerator enumerator = YieldBreak();
            while(enumerator.MoveNext())
            {
                throw new InvalidOperationException("Should not occur");
            }           
        }
        sw.Stop();

        Console.WriteLine("Yield break: {0}", sw.Elapsed);

        GC.Collect();

        sw.Restart();
        for (int i = 0; i < Iterations; i++)
        {
            IEnumerator enumerator = Enumerable.Empty<object>().GetEnumerator();
            while(enumerator.MoveNext())
            {
                throw new InvalidOperationException("Should not occur");
            }           
        }
        sw.Stop();

        Console.WriteLine("Enumerable.Empty<T>(): {0}", sw.Elapsed);

        GC.Collect();

        sw.Restart();
        var instance = new EmptyEnumerator();
        for (int i = 0; i < Iterations; i++)
        {
            while(instance.MoveNext())
            {
                throw new InvalidOperationException("Should not occur");
            }           
        }
        sw.Stop();

        Console.WriteLine("EmptyEnumerator instance: {0}", sw.Elapsed);
    }

    public static IEnumerator YieldBreak()
    {
        yield break;
    }

    private class EmptyEnumerator : IEnumerator
    {
        //public static readonly EmptyEnumerator Instance = new EmptyEnumerator();

        public bool MoveNext()
        {
            return false;
        }

        public void Reset()
        {
        }

        public object Current { get { return null; } }
    }
}
Run Code Online (Sandbox Code Playgroud)


the*_*oop 5

我使用的方法是使用空数组的枚举数:

public IEnumerator GetEnumerator() {
    return new object[0].GetEnumerator();
}
Run Code Online (Sandbox Code Playgroud)

它也可以用于通用IEnumerator或IEnumerable(使用适当类型的数组)