如何在包含IEnumerable <t>属性的类型中直接实现复杂的IEnumerable <t>?</t> </t>

时间:2011-01-14 19:17:05

标签: c# .net ienumerable

我有一个针对内部各种事物的通用集合实现:

public class ImageDocument

具有以下属性:

.Objects
.Effects
.Layers

每个基本上都是IEnumerable<T>,但我也有单独的调用,这些调用可以让我计算每一个,例如:

GetNumObjects()
GetNumEffects()
GetNumLayers()

但是这些是我想要包装的低级别成员,以及将上述属性(.Objects, .Effects, .Layers)实现为IEnumerable<T>,也使用较低级别的成员,如:

GetObject (int index)
GetEffect (int index)
GetLayer (int index)

我有自己的IEnumerable<T>类接口,它继承自IEnumerable<T>

最后我希望这些属性如下:

ICountableEnumerable Objects
ICountableEnumerable Effects
ICountableEnumerable Layers

所以我可以枚举它们,访问它们的计数(使用低级函数)以及能够索引它们:

myImageDocument.Objects.Count, etc.
myImageDocument.Objects[4]
foreach ... myImageDocument.Objects ...

我可以直接实现这些,就像在IEnumerable<T>中实现ImageDocument一样:

   public IEnumerator<Objects> GetEnumerator()
   {
      foreach(...)
      {
         yield return obj;
      }
   }

或者我是否需要每种属性的中间类型?类似的东西:

ObjectCollection
EffectCollection
LayerCollection

实现ICountableEnumerable

3 个答案:

答案 0 :(得分:4)

我可能会这样做:

class ImageDocument
{
    public ReadOnlyCollection<Effect> Effects { get { ... } }
    public ReadOnlyCollection<Layer> Layers { get { ... } }
    ...

这样用户就可以使用ReadOnlyCollection的所有优秀属性,比如count等。只读集合是一个围绕可变集合的包装器;你可以让你的可变集合逻辑作为一个实现细节工作,只是在它上面展示一个只读的包装器。

答案 1 :(得分:2)

如果你的课程中你把馆藏作为List&lt; T&gt;?然后你的IEnumerable&lt; T> .Objects等可以返回List,它将是可枚举的,并且可以通过LINQ对索引和计数进行优化。

答案 2 :(得分:1)

我建议为每种不同的枚举样式声明一个结构类型; struct应该包含对基本集合的不可变引用,并实现IEnumerable&lt; properType&gt;并公开公开一个GetEnumerator方法,该方法又会调用baseThing.GetLayersEnumerator()或其他一些类似的函数。这种方法可以避免在许多常见的使用场景中进行装箱,并且 - 与List.GetEnumerator之类的东西返回的结构不同 - 将显示引用语义,无论它是否已装箱。