我应该定义自定义枚举器还是使用内置枚举器?

时间:2013-05-13 10:21:27

标签: c#

我收到了一些客户的代码,如下所示:

public class Thing
{
    // custom functionality for Thing...
}

public class Things : IEnumerable
{
    Thing[] things;
    internal int Count { get { return things.Length; } }

    public Thing this[int i] { get { return this.things[i]; } }

    public IEnumerator GetEnumerator() { return new ThingEnumerator(this); }

    // custom functionality for Things...
}

public class ThingEnumerator : IEnumerator
{
    int i;
    readonly int count;
    Things container;

    public ThingEnumerator(Things container)
    {
        i = -1;
        count = container.Count;
        this.container = container;
    }

    public object Current { get { return this.container[i]; } }
    public bool MoveNext() { return ++i < count; }
    public void Reset() { i = -1; }
}

我想知道的是,摆脱ThingEnumerator课程并将Things.GetEnumerator调用替换为仅委托给array的实现是否会更好s GetEnumerator?像这样:

public IEnumerator GetEnumerator() { return things.GetEnumerator(); }

保持代码原样有什么好处吗? (我注意到的另一件事是,可以通过将IEnumerator替换为IEnumerator<Thing>来改进现有代码。)

5 个答案:

答案 0 :(得分:3)

使用泛型,自己实施IEnumerableIEnumerator几乎没有价值。

删除这些正在用通用集合替换类意味着您需要维护的代码少得多,并且具有使用已知可用的代码的优势。

答案 1 :(得分:2)

在一般情况下,有时可能有理由实施自己的枚举器。您可能需要一些内置的功能不提供的功能 - 一些验证,日志记录,在某处提升OnAccess类型事件,可能是一些逻辑来锁定项目并在之后释放它们以进行并发访问(我见过这样做的代码)最后一个;它很奇怪,我不推荐它。)

话虽如此,我在您发布的示例中看不到类似内容,因此它似乎没有添加超出IEnumerable提供的任何值。通常,如果有内置代码可以执行您想要的操作,请使用它。通过自己动手来实现的就是创建更多代码来维护。

答案 2 :(得分:2)

在.NET泛型可用之前,您所拥有的代码看起来像是为.NET 1.0 / 1.1编写的代码 - 那时,实现您自己的集合类(通常派生自System.Collections.CollectionBase)是有价值的以便可以将indexer属性键入到集合的运行时类型中。 但是,除非您使用值类型并且装箱/取消装箱是性能限制因素,否则我将继承CollectionBase并且无需重新定义GetEnumerator()Count

但是,现在,我建议采用以下两种方法之一:

  1. 如果您需要自定义集合具有某些自定义功能,则从System.Collections.ObjectModel.Collection<Thing>派生集合 - 它为您提供了控制集合中项目的插入,替换和删除的所有必要挂钩。

  2. 如果您实际上只需要需要枚举的内容,我会返回由IList<Thing>支持的标准List<Thing>

答案 3 :(得分:1)

除非您在自定义枚举器中执行真正自定义(例如某种验证)的操作,否则没有任何理由不执行此操作。

一般情况下,除非有明确的理由,否则请使用标准库中提供的内容。它们可能经过更好的测试,并且有更多的时间花在它们上,作为单独的代码单元,然后你可以负担得起,以及为什么重新创建轮子?

在这种情况下,代码已经存在,但如果你有时间进行测试,替换代码可能仍然会更好。 (如果有适当的单元测试覆盖率,这是一个明智的选择。)

您将减少维护开销,消除潜在的模糊错误源并使代码比您发现的更干净。鲍勃叔叔会很自豪。

答案 4 :(得分:1)

数组枚举器与自定义枚举器几乎完全相同,所以是的,你也可以直接返回数组的枚举器。
在这种情况下,我建议你这样做,因为数组枚举器也执行更多的错误检查,正如你所说,它只是更简单。