示例:
using System;
using System.Collections;
public class List
{
public static IEnumerable Power(int number, int exponent)
{
int counter = 0;
int result = 1;
while (counter++ < exponent)
{
result = result * number;
yield return result;
}
}
static void Main()
{
// Display powers of 2 up to the exponent 8:
foreach (int i in Power(2, 8))
{
Console.Write("{0} ", i);
}
}
}
如果热切评估收益率算子,我的猜测是:
public static IEnumerable Power(int number, int exponent)
{
int counter = 0;
int result = 1;
List<int> powers;
while (counter++ < exponent)
{
result = result * number;
powers.add(result);
}
return powers;
}
我不知道如果对yield运算符进行延迟计算,它会是什么样子。
更新: Reflector提供了这个:
public class List
{
// Methods
public List();
private static void Main();
public static IEnumerable Power(int number, int exponent);
// Nested Types
[CompilerGenerated]
private sealed class <Power>d__0 : IEnumerable<object>, IEnumerable, IEnumerator<object>, IEnumerator, IDisposable
{
// Fields
private int <>1__state;
private object <>2__current;
public int <>3__exponent;
public int <>3__number;
private int <>l__initialThreadId;
public int <counter>5__1;
public int <result>5__2;
public int exponent;
public int number;
// Methods
[DebuggerHidden]
public <Power>d__0(int <>1__state);
private bool MoveNext();
[DebuggerHidden]
IEnumerator<object> IEnumerable<object>.GetEnumerator();
[DebuggerHidden]
IEnumerator IEnumerable.GetEnumerator();
[DebuggerHidden]
void IEnumerator.Reset();
void IDisposable.Dispose();
// Properties
object IEnumerator<object>.Current { [DebuggerHidden] get; }
object IEnumerator.Current { [DebuggerHidden] get; }
}
}
IEnumerator<object> IEnumerable<object>.GetEnumerator()
{
List.<Power>d__0 d__;
if ((Thread.CurrentThread.ManagedThreadId == this.<>l__initialThreadId) && (this.<>1__state == -2))
{
this.<>1__state = 0;
d__ = this;
}
else
{
d__ = new List.<Power>d__0(0);
}
d__.number = this.<>3__number;
d__.exponent = this.<>3__exponent;
return d__;
}
private bool MoveNext()
{
switch (this.<>1__state)
{
case 0:
this.<>1__state = -1;
this.<counter>5__1 = 0;
this.<result>5__2 = 1;
while (this.<counter>5__1++ < this.exponent)
{
this.<result>5__2 *= this.number;
this.<>2__current = this.<result>5__2;
this.<>1__state = 1;
return true;
Label_0065:
this.<>1__state = -1;
}
break;
case 1:
goto Label_0065;
}
return false;
}
答案 0 :(得分:11)
首先,yield不是运算符。 yield return和yield break是语句。
有很多关于编译器如何实现迭代器块的文章。从迭代器块上的读取C#规范部分开始;它为C#的实现者如何想要它提供了一些建议。
接下来阅读Raymond Chen的系列文章“C#中迭代器的实现及其后果”
http://www.bing.com/search?q=raymond+chen+the+implementation+of+iterators
接下来,阅读Jon Skeet关于这个主题的书籍章节:
http://csharpindepth.com/Articles/Chapter6/IteratorBlockImplementation.aspx
如果毕竟您仍然感兴趣,那么请阅读我关于此功能的设计因素的系列文章:
答案 1 :(得分:7)
回到过去,在我们使用yield运算符之前,我们曾经编写过实现IEnumerator的类。
class PowerEnumerator : IEnumerator<int>
{
private int _number;
private int _exponent;
private int _current = 1;
public PowerEnumerator(int number, int exponent)
{
_number = number;
_exponent = exponent;
}
public bool MoveNext()
{
_current *= number;
return _exponent-- > 0;
}
public int Current
{
get
{
if (_exponent < 0) throw new InvalidOperationException();
return _current;
}
}
}
或类似的东西。这不好玩,让我告诉你。
答案 2 :(得分:0)
IEnumerable<T>
的自定义实现,而不是依赖于List<T>
有关详情here。
答案 3 :(得分:0)
yield
非常有效的原因。