我有一个接口,除其他外,实现了一个"公共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语句强制编译器将其视为迭代器块.
这将比"自定义"空迭代器效率低,但它的代码更简单......
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)
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)
我很好奇,走得更远。我做了一个测试,检查,如何有效的方法比较yield break,Enumerable.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)
我使用的方法是使用空数组的枚举数:
public IEnumerator GetEnumerator() {
return new object[0].GetEnumerator();
}
Run Code Online (Sandbox Code Playgroud)
它也可以用于通用IEnumerator或IEnumerable(使用适当类型的数组)