我收到了一些客户的代码,如下所示:
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>
来改进现有代码。)
答案 0 :(得分:3)
使用泛型,自己实施IEnumerable
和IEnumerator
几乎没有价值。
删除这些正在用通用集合替换类意味着您需要维护的代码少得多,并且具有使用已知可用的代码的优势。
答案 1 :(得分:2)
在一般情况下,有时可能有理由实施自己的枚举器。您可能需要一些内置的功能不提供的功能 - 一些验证,日志记录,在某处提升OnAccess类型事件,可能是一些逻辑来锁定项目并在之后释放它们以进行并发访问(我见过这样做的代码)最后一个;它很奇怪,我不推荐它。)
话虽如此,我在您发布的示例中看不到类似内容,因此它似乎没有添加超出IEnumerable
提供的任何值。通常,如果有内置代码可以执行您想要的操作,请使用它。通过自己动手来实现的就是创建更多代码来维护。
答案 2 :(得分:2)
在.NET泛型可用之前,您所拥有的代码看起来像是为.NET 1.0 / 1.1编写的代码 - 那时,实现您自己的集合类(通常派生自System.Collections.CollectionBase
)是有价值的以便可以将indexer属性键入到集合的运行时类型中。
但是,除非您使用值类型并且装箱/取消装箱是性能限制因素,否则我将继承CollectionBase
并且无需重新定义GetEnumerator()
或Count
。
但是,现在,我建议采用以下两种方法之一:
如果您需要自定义集合具有某些自定义功能,则从System.Collections.ObjectModel.Collection<Thing>
派生集合 - 它为您提供了控制集合中项目的插入,替换和删除的所有必要挂钩。
如果您实际上只需要需要枚举的内容,我会返回由IList<Thing>
支持的标准List<Thing>
。
答案 3 :(得分:1)
除非您在自定义枚举器中执行真正自定义(例如某种验证)的操作,否则没有任何理由不执行此操作。
一般情况下,除非有明确的理由,否则请使用标准库中提供的内容。它们可能经过更好的测试,并且有更多的时间花在它们上,作为单独的代码单元,然后你可以负担得起,以及为什么重新创建轮子?
在这种情况下,代码已经存在,但如果你有时间进行测试,替换代码可能仍然会更好。 (如果有适当的单元测试覆盖率,这是一个明智的选择。)
您将减少维护开销,消除潜在的模糊错误源并使代码比您发现的更干净。鲍勃叔叔会很自豪。
答案 4 :(得分:1)
数组枚举器与自定义枚举器几乎完全相同,所以是的,你也可以直接返回数组的枚举器。
在这种情况下,我建议你这样做,因为数组枚举器也执行更多的错误检查,正如你所说,它只是更简单。