C# 返回一个空的 IEnumerator
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1714351/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Return an empty IEnumerator
提问by David Bo?jak
I have an interface that, among other things, implements a "public IEnumerator GetEnumerator()" method, so I can use the interface in a foreach statement.
我有一个接口,除其他外,它实现了“公共 IEnumerator GetEnumerator()”方法,因此我可以在 foreach 语句中使用该接口。
I implement this interface in several classes and in one of them, I want to return an empty IEnumerator. Right now I do this the following way:
我在几个类中实现了这个接口,在其中一个类中,我想返回一个空的 IEnumerator。现在我按以下方式执行此操作:
public IEnumerator GetEnumerator()
{
ArrayList arr = new ArrayList();
return arr.GetEnumerator();
}
However I consider this an ugly hack, and I can't help but think that there is a better way of returning an empty IEnumerator. Is there?
然而,我认为这是一个丑陋的黑客,我不禁认为有更好的方法来返回一个空的 IEnumerator。在那儿?
采纳答案by Jon Skeet
This is simple in C# 2:
这在 C# 2 中很简单:
public IEnumerator GetEnumerator()
{
yield break;
}
You need the yield break
statement to force the compiler to treat it as an iterator block.
您需要该yield break
语句来强制编译器将其视为迭代器块。
This will be less efficient than a "custom" empty iterator, but it's simpler code...
这将比“自定义”空迭代器效率低,但它是更简单的代码......
回答by Ikke
回答by Arsen Mkrtchyan
You can implement IEnumerator interface and IEnumerable, and return false from MoveNext function of IEnumerable interfase
可以实现IEnumerator接口和IEnumerable,IEnumerable接口的MoveNext函数返回false
private class EmptyEnumerator : IEnumerator
{
public EmptyEnumerator()
{
}
#region IEnumerator Members
public void Reset() { }
public object Current
{
get
{
throw new InvalidOperationException();
}
}
public bool MoveNext()
{ return false; }
}
public class EmptyEnumerable : IEnumerable
{
public IEnumerator GetEnumerator()
{
return new EmptyEnumerator();
}
}
回答by Konamiman
You could implement a dummy class that implements IEnumerator, and return an instance of it:
您可以实现一个实现 IEnumerator 的虚拟类,并返回它的一个实例:
class DummyEnumerator : IEnumerator
{
public object Current
{
get
{
throw new InvalidOperationException();
}
}
public bool MoveNext()
{
return false;
}
public void Reset()
{
}
}
回答by thecoop
The way I use is to use the enumerator of an empty array:
我使用的方法是使用空数组的枚举器:
public IEnumerator GetEnumerator() {
return new object[0].GetEnumerator();
}
It can also be used for generic IEnumerator or IEnumerable (use an array of the appropriate type)
它也可以用于泛型 IEnumerator 或 IEnumerable(使用适当类型的数组)
回答by user287107
There is an extra function in the framework:
框架中有一个额外的功能:
public static class Enumerable
{
public static IEnumerable<TResult> Empty<TResult>();
}
Using this you can write:
使用这个你可以写:
var emptyEnumerable = Enumerable.Empty<int>();
var emptyEnumerator = Enumerable.Empty<int>().GetEnumerator();
回答by Johan Larsson
I wrote it like this:
我是这样写的:
public IEnumerator<T> GetEnumerator()
{
return this.source?.GetEnumerator() ??
Enumerable.Empty<T>().GetEnumerator();
}
回答by Santhos
I was curious and went a bit further. I made a test that checks how efficient the methods are comparing yield break
, Enumerable.Emtpy
and custom class.
我很好奇,走得更远。我做了一个测试,检查,如何有效的方法比较yield break
,Enumerable.Emtpy
和自定义类。
You can check it out on dotnetfiddle https://dotnetfiddle.net/vTkmcQor use the code below.
您可以在 dotnetfiddle https://dotnetfiddle.net/vTkmcQ上查看或使用下面的代码。
The result of one of the many dotnetfiddle runs using 190 000 iterations was:
使用 190 000 次迭代的许多 dotnetfiddle 运行之一的结果是:
Yield break: 00:00:00.0210611
Enumerable.Empty(): 00:00:00.0192563
EmptyEnumerator instance: 00:00:00.0012966
收益率中断: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; } }
}
}
回答by BlueMonkMN
Found this question looking for the simplest way to get an empty enumerator. After seeing the answer comparing performance I decided to use the empty enumerator class solution, but mine is more compact than the other examples, and is a generic type, and also provides a default instance so you don't have to create new instances all the time, which should even further improve performance.
发现这个问题正在寻找获取空枚举器的最简单方法。在看到比较性能的答案后,我决定使用空枚举器类解决方案,但我的比其他示例更紧凑,并且是通用类型,并且还提供了一个默认实例,因此您不必创建新实例时间,这应该会进一步提高性能。
class EmptyEnumerator<T> : IEnumerator<T>
{
public readonly static EmptyEnumerator<T> value = new EmptyEnumerator<T>();
public T Current => throw new InvalidOperationException();
object IEnumerator.Current => throw new InvalidOperationException();
public void Dispose() { }
public bool MoveNext() => false;
public void Reset() { }
}