开发者

How to implement a complex IEnumerable<T> directly inside the type containing the IEnumerable<T> property?

I have a generic collection implementation for various things that's inside:

public class ImageDocument

with properties like:

.Objects
.Effects
.Layers

each of which is basically IEnumerable<T>, but I 开发者_高级运维also have separate calls that gives me the count for each of these, something like:

GetNumObjects()
GetNumEffects()
GetNumLayers()

but these are lower level members that I want to wrap as well as implement the above properties (.Objects, .Effects, .Layers) as IEnumerable<T>, also using lower level members like:

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

I have my own IEnumerable<T> like interface that inherits from IEnumerable<T>.

In the end I want these properties to be like this:

ICountableEnumerable Objects
ICountableEnumerable Effects
ICountableEnumerable Layers

so I could both enumerate them, access their counts (using the low level functions) as well as to be able to index them:

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

Can I implement these directly just like implementing IEnumerable<T> inside ImageDocument like:

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

or do I need an intermediate type for each of these properties? Something like:

ObjectCollection
EffectCollection
LayerCollection

that implements ICountableEnumerable?


I would probably do something like:

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

That way the user can use all the nice properties of ReadOnlyCollection, like count, etc. The read-only-collection is a wrapper around a mutable collection; you can keep your mutable collection logic working as an implementation detail, and just expose a read-only wrapper on top of it.


What if within your class you held the collections as List < T >? Then your IEnumerable < T > .Objects, et al, can return the List which would be enumerable AND optimized for index and count by LINQ.


I would suggest declaring a struct type for each of the different styles of enumeration; the struct should hold an immutable reference to the base collection, and implement IEnumerable<appropriateType> and publicly expose a GetEnumerator method, which would in turn call baseThing.GetLayersEnumerator() or some other similar function. Such an approach would avoid boxing in many common usage scenarios, and--unlike the structs returned by things like List.GetEnumerator--would exhibit reference semantics whether or not it was boxed.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜