Nested shared collections: how to implement a link from an element to a container?

When implementing design using nested shared collections, I came across those restrictions that were apparently caused by C # invariants:

  Cannot convert from 'Collection <subtype of T> to' Collection <T> ' 

This means that the following will not work, apparently due to Generics invariance:

class Outer<TInner, TInnerItem> where TInner : Inner<TInnerItem> { public void Add(TInner item) { item.Outer = this; // ERROR: // Cannot implicitly convert from Outer<TInner, TInnerItem> // to Outer<Inner<TInnerItem>, TInnerItem> } } class Inner<TInnerItem> : ICollection<TInnerItem> { Outer<Inner<TInnerItem>, TInnerItem> _outer; public Outer<Inner<TInnerItem>, TInnerItem> Outer { set { _outer = value; } } } 

(In actual code, both Inner<> and Outer<> implement ICollection<> .)

I need Inner<> objects to have a link to its collection of containers in order to access some of my data.

How would you implement these nested collections, preferably using a generic approach, as described above? How would you set up a container collection reference in the Inner<> class?

Hooray!

+4
source share
2 answers

Representing a (possibly abstract) base class independent of TInner can help you:

 abstract class OuterBase<TInnerItem> { } class Outer<TInner, TInnerItem> : OuterBase<TInnerItem> where TInner : Inner<TInnerItem> { public void Add(TInner item) { item.Outer = this; // Compiles } } class Inner<TInnerItem> : ICollection<TInnerItem> { OuterBase<TInnerItem> _outer; public OuterBase<TInnerItem> Outer { set { _outer = value; } } } 

Or wait for C # 4.0, which introduces shared / conflicting common interfaces.

+2
source

The language cannot allow you to convert from Collection <subtype T> to collection <T>

Let me explain why.

Imagine you have a collection <subT> and discard it in Collection <T>. This is normal since subT inherits from T.

When you retrieve an object from collection_of_T , you are sure that everything is in order.

Add the T object to collection_of_T later. You now have a collection_of_subT object that is not a subT . Oops

To achieve what you want, you must create a new collection alltogether.

 Collection<T> collection_of_T = new Collection<T>(collection_of_subT); 

This is most likely not good for you. Do you really need a generic TInner argument in the Outer class? Is it possible to replace the Inner<TInnerItem> in the rest of the code instead?

0
source

All Articles