考虑以下简单的示例:
class Filter<T, U>
where T : IEnumerable<U>
where U : IEquatable<U>
{
private readonly U id;
public Filter(U id) => this.id = id;
public T Eval_A(T items)
{
foreach (var item in items)
if (item.Equals(id))
yield return item;
}
public IEnumerable<U> Eval_B(IEnumerable<U> items)
{
foreach (var item in items)
if (item.Equals(id))
yield return item;
}
}即使T是IEnumerable<U>类型,T Eval_A(T items)仍然会发生如下错误。
“访问器”的主体不能是迭代器块,因为“类型”不是迭代器接口类型。
MSDN说:
如果使用迭代器访问器,但返回类型不是迭代器接口类型之一:
IEnumerable、IEnumerable<T>、IEnumerator、IEnumerator<T>,则会发生此错误。若要避免此错误,请使用迭代器接口类型之一作为返回类型。
我认为返回类型符合要求。
我在这里错过了什么?
发布于 2022-09-07 06:57:47
方法的返回类型必须是IEnumerable、IEnumerable<T>、IEnumerator或IEnumerator<T>中的一种,而不是实现IEnumerable<U>的某种类型的T。
这是因为迭代器方法的工作方式是编译器生成实现上述接口之一的类型,MoveNext和Current实现正确,以便与方法的行为匹配,然后重写方法以返回该类型的实例。
例如,对于以下方面:
public IEnumerable<int> GetSingleDigitNumbersLoop()
{
int index = 0;
while (index < 10)
yield return index++;
}生成以下内容(参见使用SharpLab.io):
[IteratorStateMachine(typeof(<GetSingleDigitNumbersLoop>d__0))]
public IEnumerable<int> GetSingleDigitNumbersLoop()
{
return new <GetSingleDigitNumbersLoop>d__0(-2);
}
[CompilerGenerated]
private sealed class <GetSingleDigitNumbersLoop>d__0 : IEnumerable<int>, IEnumerable, IEnumerator<int>, IDisposable, IEnumerator
{
private int <>1__state;
private int <>2__current;
private int <>l__initialThreadId;
private int <index>5__2;
int IEnumerator<int>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <GetSingleDigitNumbersLoop>d__0(int <>1__state)
{
this.<>1__state = <>1__state;
<>l__initialThreadId = Environment.CurrentManagedThreadId;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
}
private bool MoveNext()
{
int num = <>1__state;
if (num != 0)
{
if (num != 1)
{
return false;
}
<>1__state = -1;
}
else
{
<>1__state = -1;
<index>5__2 = 0;
}
if (<index>5__2 < 10)
{
<>2__current = <index>5__2++;
<>1__state = 1;
return true;
}
return false;
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
[DebuggerHidden]
IEnumerator<int> IEnumerable<int>.GetEnumerator()
{
if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
{
<>1__state = 0;
return this;
}
return new <GetSingleDigitNumbersLoop>d__0(0);
}
[DebuggerHidden]
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<int>)this).GetEnumerator();
}
}<GetSingleDigitNumbersLoop>d__0是实现IEnumerable<int>的类型,而GetSingleDigitNumbersLoop则被重写为返回。
现在,如果声明GetSingleDigitNumbersLoop返回其他类型,例如类型参数T,下面的内容将无法工作:
public T GetSingleDigitNumbersLoop()
{
return new <GetSingleDigitNumbersLoop>d__0(-2);
}因为<GetSingleDigitNumbersLoop>d__0不一定是T。事实上,它几乎永远不会是,因为它是一个编译器生成的类型!
另见:产量报表实现
https://stackoverflow.com/questions/73631107
复制相似问题