开发者

Casting problems with connected Generic classes

开发者 https://www.devze.com 2022-12-09 05:33 出处:网络
Here\'s a thinned out version of the classes I have. public abstract class BaseParent { } public abstract class ChildCollectionItem<T>

Here's a thinned out 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>
{
开发者_如何学Python  // 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 realize this problem is probably due to the fact that the ChildCollection class isn't aware of the type constraints set in ChildCollectionItem, because if it was there shouldn't be a problem here. Type 'U' should always be a ChildCollectionItem where the ChildCollectionItem 'T' is always the same as the ChildCollection 'T'.

What I need to know is if there is a way I can cast 'this' so that it compiles, or modify my classes / constraints so the compiler can handle this without a cast.


The problem is one of variance - U could be some type other than just ChildCollectionItem<T> - it could be a type derived from ChildCollectionItem<T>, and Foo<DerivedClass> isn't compatible with Foo<BaseClass>.

How about introducing another generic base class to 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;
  }
}


this problem is probably due to the fact that the ChildCollection class isn't aware of the type constraints set in ChildCollectionItem, because if it was there shouldn't be a problem here.

The statement above is incorrect.

Type 'U' should always be a ChildCollectionItem where the ChildCollectionItem 'T' is always the same as the ChildCollection 'T'.

How do you figure that? U is guaranteed via its constraint to be convertible via reference conversion to that type. It is not guaranteed to be that type, which is what is required. U could be any type derived from that type.

If U is always that type, then why is there a "U" in the first place? Why not just eliminate the type parameter entirely and replace every usage of it with the type you expect it to be?


Your constraint on U is very specific; U has to be of type ChildCollectionItem. Would it be possible in your application to define the collection as

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

That would eliminate the need to cast.

0

精彩评论

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