C# 我应该定义自定义枚举数还是使用内置枚举数?

C# 我应该定义自定义枚举数还是使用内置枚举数?,c#,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.thing

我从一位客户那里得到了如下代码:

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; }
}

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

使用泛型,实现
IEnumerable
IEnumerator
实际上没有什么价值


删除它们意味着用泛型集合替换类意味着您需要维护的代码要少得多,并且具有使用已知可用代码的优势。

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

一般来说,除非有明确的理由不这样做,否则应使用标准库中提供的内容。它们可能经过更好的测试,并且在它们上花费了更多的时间,作为单独的代码单元,那么您就可以负担得起,为什么要重新创建轮子呢

在这种情况下,代码已经存在,但是如果您有时间进行很好的测试,那么最好还是替换代码。(如果有合适的单元测试覆盖率,这是一个不需要动脑筋的问题。)


您将减少维护开销,消除潜在的不明bug源,并使代码比您发现的更干净。Bob叔叔会很自豪的。

数组枚举器的作用与您的自定义枚举器几乎相同,因此是的,您也可以直接返回数组的枚举器。

在本例中,我建议您这样做,因为数组枚举数还执行更多的错误检查,并且,正如您所说的,它更简单

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


话虽如此,在您发布的示例中,我看不到任何类似的内容,因此它似乎没有添加任何超出
IEnumerable
提供的值。作为一项规则,如果有内置代码满足您的需求,请使用它。通过滚动您自己的代码,您所能实现的就是创建更多要维护的代码。

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

但是,现在,我推荐以下两种方法之一:

  • 如果您需要自定义集合具有一些自定义功能,那么从中派生集合-它为您提供了控制集合中项目的插入、替换和删除所需的所有钩子

  • 如果您实际上只需要一些需要枚举的内容,我将返回一个标准的
    IList
    ,后面有一个
    列表


  • 你的直觉是对的。在c#出现泛型之前,这段代码很旧。可以用public IEnumerable GoForward(){foreach(things中的var t)yield return t;}替换GetEnumerator,并使用things=newthings()迭代类;foreach(var t in things){…}@graumanoz考虑到这一点,这可能是客户使用了很长时间的旧代码,如果他们从头开始编写类似的代码,他们将使用更现代的方法。TooTone是的,这是一个旧代码:)它可以完全被我以前编写的小方法所取代,顺便说一下,现代方法。
    public IEnumerator GetEnumerator() { return things.GetEnumerator(); }