首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >即使返回类型为IEnumerable<U>,也无法生成

即使返回类型为IEnumerable<U>,也无法生成
EN

Stack Overflow用户
提问于 2022-09-07 06:41:34
回答 1查看 42关注 0票数 0

考虑以下简单的示例:

代码语言:javascript
复制
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;
    }
}

即使TIEnumerable<U>类型,T Eval_A(T items)仍然会发生如下错误。

“访问器”的主体不能是迭代器块,因为“类型”不是迭代器接口类型。

MSDN说:

如果使用迭代器访问器,但返回类型不是迭代器接口类型之一:IEnumerableIEnumerable<T>IEnumeratorIEnumerator<T>,则会发生此错误。若要避免此错误,请使用迭代器接口类型之一作为返回类型。

我认为返回类型符合要求。

我在这里错过了什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-09-07 06:57:47

方法的返回类型必须是IEnumerableIEnumerable<T>IEnumeratorIEnumerator<T>中的一种,而不是实现IEnumerable<U>的某种类型的T

这是因为迭代器方法的工作方式是编译器生成实现上述接口之一的类型,MoveNextCurrent实现正确,以便与方法的行为匹配,然后重写方法以返回该类型的实例。

例如,对于以下方面:

代码语言:javascript
复制
public IEnumerable<int> GetSingleDigitNumbersLoop()
{
    int index = 0;
    while (index < 10)
        yield return index++;
}

生成以下内容(参见使用SharpLab.io):

代码语言:javascript
复制
[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,下面的内容将无法工作:

代码语言:javascript
复制
public T GetSingleDigitNumbersLoop()
{
    return new <GetSingleDigitNumbersLoop>d__0(-2);
}

因为<GetSingleDigitNumbersLoop>d__0不一定是T。事实上,它几乎永远不会是,因为它是一个编译器生成的类型!

另见:产量报表实现

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73631107

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档