Casting problems in related classes

Here's a refined version of the classes I have.

public abstract class BaseParent { }

public abstract class ChildCollectionItem<T>
  where T : BaseParent
{
  // References a third-party object that acts as the parent to both the collection 
  // items and the collection itself.
  public T parent;

  // References the collection to which this item belongs. The owning collection
  // will share the same parent type. The second type argument indicates what
  // type of items the collection will store. 
  public ChildCollection<T, ChildCollectionItem<T>> owningCollection;
}

public abstract class ChildCollection<T, U> : CollectionBase
  where T : BaseParent
  where U : ChildCollectionItem<T>
{
  // References a third-party object that acts as the parent to both the collection 
  // items and the collection itself.
  public T parent;

  // Adds an item of type 'U' to the collection. When added, I want to set the 
  // owningCollection value of the item to 'this' collection.
  public int Add(U item)
  {
    int indexAdded = this.List.Add(item);

    // THIS LINE IS THROWING A COMPILE ERROR - Cannot convert type 
    // 'ChildCollection<T, U>' to 'ChildCollection<T, ChildCollectionItem<T>>'
    item.owningCollection = this;

    return indexAdded;
}

      

I understand that this problem is probably due to the fact that the ChildCollection class does not know the type constraints set on the ChildCollectionItem, because if it did, there would be no problem here. Type 'U' must always be a ChildCollectionItem, where ChildCollectionItem 'T' is always the same as ChildCollection 'T'.

I need to know if there is a way that I can use 'this' so that it compiles or modifies my classes / constraints so the compiler can handle this without casting.

+2


source to share


3 answers


The problem is variance - U can be a different type than just ChildCollectionItem<T>

- it can be a type derived from ChildCollectionItem<T>

and Foo<DerivedClass>

not compatible with Foo<BaseClass>

.

How about introducing another base class in ChildCollection<T, U>

?



using System.Collections;

public abstract class BaseParent { }

public abstract class ChildCollectionItem<T>
  where T : BaseParent
{
  public T parent;

  public ChildCollection<T> owningCollection;
}

public abstract class ChildCollection<T> : CollectionBase
  where T : BaseParent
{
}

public abstract class ChildCollection<T, U> : ChildCollection<T>
  where T : BaseParent
  where U : ChildCollectionItem<T>
{
  public T parent;

  public int Add(U item)
  {
    int indexAdded = this.List.Add(item);
    item.owningCollection = this;
    return indexAdded;
  }
}

      

+4


source


this problem is probably due to the fact that the ChildCollection class does not know the type of constraints set on the ChildCollectionItem, because if that were there there should be no problem.

The above statement is not correct.

Type 'U' must always be ChildCollectionItem, where ChildCollectionItem 'T' is always the same as ChildCollection 'T'.



How do you understand this? U is guaranteed, through its constraint, to be convertible by reference conversion to this type. The type that is required is not guaranteed. U can be any type derived from that type.

If U is always a type, then why is "U" in the first place? Why not just eliminate the type parameter entirely and replace all of its use with the type you expect?

+4


source


Your U limit is very specific; U must be of type ChildCollectionItem. Is it possible in your application to define a collection as

public abstract class ChildCollection<T, ChildCollectionItem<T>>

      

This saves you the trouble of quitting.

0


source







All Articles