实现无限枚举数和可枚举数是否是错误的做法?

时间:2018-10-21 15:15:12

标签: c# .net oop ienumerable ienumerator

我有以下课程:

class CopyProvider<T> where T: IMyCloneable
{
    private readonly T _original;

    public CopyProvider(T original) => _original = original;

    public T Current { get; private set; }

    public bool MoveNext()
    {
        Current = _original.Clone();
        return true;
    }
}

现在,我想知道将此类声明为IEnumerator<T>的实现是否是一个好习惯。从句法的角度来看,CopyProvider确实符合要求,但是会违反IEnumerator的语义吗?

或者,我也可以编写以下方法:

IEnumerable<T> ProvideCopies<T>(T original) where T: IMyCloneable
{
    while(true)
        yield return original.Clone();
}

的确,这会舒服得多。但是同样,我遇到了同样的问题:IEnumerable的这种用法会破坏接口的语义吗?

还是应该考虑使用InfiniteEnumerator和/或InfiniteEnumerable实现单独的对象结构?但是,这将使我无法使用yieldforeach之类的C#语法糖。

我期待您的推荐。

2 个答案:

答案 0 :(得分:1)

如果您的枚举永远不会停止产生结果,则最好要求开发人员明确说明要产生的最大金额是多少,从而消除开发人员使用{{ 1}}语法与您的枚举。例如

for each

或者,如果您是老学校:

IEnumerable<T> ProvideCopies<T>(T original, int howMany) where T: IMyCloneable<T>
{
    return Enumerable.Range(1, howMany).Select(x => original.Clone());
}

那样,开发人员没有有义务消耗整个枚举,并且可以随时停止(即,您仍在屈服),但是您知道它会在某个时刻停止,而不是因为代码中的错误而导致代码永久性地阻塞生产的可能性。


如果您真的无法确定需要多少份副本,并且需要继续生成副本,直到有其他情况告诉您停止,那么IEnumerable<T> ProvideCopies<T>(T original, int howMany) where T: IMyCloneable<T> { for (var i = 0; i < howMany; i++) yield return original.Clone(); } 会更适合该情况,因为它的目的是“一直听”,直到您IObservable<T>为止。

  

IObservable Interface

答案 1 :(得分:-2)

是的,我认为这确实是不好的做法。线程将无法处理任何其他代码路径。这会给处理器带来很多负担。