2013-05-13 72 views
3

我一直在考虑从客户,看起来像这样的代码:我应该定义自定义的枚举器还是使用内置的枚举器?

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通话一个实现只是委托给arrayGetEnumerator?像这样:

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

保持代码原样有什么好处吗? (我注意到另一件事是,现有的代码可以用IEnumerator<Thing>更换IEnumerator得到改善。)

+0

您的直觉是对的。在Generics来到C#之前,这段代码是旧的。 你可以用 替换GetEnumerator public IEnumerable GoForward(){foreach(var t in things)yield return t; } 为了迭代你的类,使用Things things = new Things(); foreach(var t in things){...} – graumanoz 2013-05-13 10:28:28

+0

@graumanoz考虑到这一点,这可能是客户长时间敲响的_old_代码,如果他们从头开始写类似的话,他们会使用更现代的方法。 – TooTone 2013-05-13 10:41:10

+0

TooTone 是的,这是一个旧的代码:) 它可以完全取代我以前写的小方法,顺便说一句,现代的方法。 – graumanoz 2013-05-13 10:52:09

回答

2

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

说了这么多,我在你发布的例子中看不到类似的东西,所以它似乎没有增加任何超出IEnumerable提供的值的值。通常,如果有内置的代码可以实现您想要的功能,请使用它。所有你通过滚动你自己来实现的就是创建更多的代码来维护。

3

随着仿制药,没有实施IEnumerableIEnumerator自己真的没有什么价值。

删除这些是用泛型集合取代类意味着你有更少的代码来维护并具有使用已知工作的代码的优势。

1

除非你在自定义枚举器中做了一些真正自定义的事情(比如某种验证),否则确实没有任何理由这样做。

一般情况下,除非有明确的理由,否则请使用标准库中的可用内容。他们可能会得到更好的测试,并花费更多时间在他们身上,作为单独的代码单元,那么您可以负担得起花费,为什么重新创建轮子?

在这种情况下,代码已经存在,但如果您有时间测试的话,代码可能会更好。 (如果单元测试覆盖率不错,那么这是一个不容小觑的过程。)

您将减少维护开销,消除潜在错误隐患并保持代码清洁。鲍伯叔叔会感到骄傲。

1

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

2

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

但是,现在,我会建议这两种方法之一:

  1. 如果您需要自定义集合有一些自定义的功能,然后从System.Collections.ObjectModel.Collection<Thing>获得集合 - 它提供了所有必要的挂钩您可以控制集合中项目的插入,替换和删除。

  2. 如果您实际上只需要枚举某些东西,我会返回一个由List<Thing>支持的标准IList<Thing>