LukeHennerley
LukeHennerley

Reputation: 6434

Trouble casting an object which inherits from a generic base

I am trying to get to grips with more complicated inheritance structures and generics and I am trying to create some architecture for a current project which is following this suit. My problem currently is I am getting this error:

Type argument 'Foo' does not inherit from or implement the constraint type 'ListBase'

  public class ItemBase {}
  public class ListBase<T> where T : ItemBase
  {
    public virtual List<T> ListExample {get; set; }
  }

These are my base classes, although they probably aren't named appropriately I have just tried to show a simple example of what I am trying to achieve.

  public class FooItem : ItemBase { }
  public class Foo : ListBase<FooItem>
  {
    public override List<FooItem> ListExample { get; set;}
  }

So I can then extend the initial base class for the lists and do more with it, but I want a generic way of handling all of these classes.

  public class ListHandler<T> where T : ListBase<ItemBase> { }

When I try to pass Foo as T to the ListHandler I get the error mentioned, I thought that inevitably because Foo is a List<ItemBase> and FooItem is of type ItemBase I would be able to do this var handler = new ListHandler<Foo>();.

Could anybody explain why I can't do this or what I am doing wrong?

Upvotes: 1

Views: 89

Answers (2)

Joshua Honig
Joshua Honig

Reputation: 13215

You need to supply the type parameter of the item type, not the list type. To clarify this, try expanding the ListHandler class to include an AddItem method which adds a ItemBase item to a ListBase instance:

// As is: Won't work, because there is no way to refer to the constructed
// specific type of ItemBase:
public class ListHandler<TList> where TList: ListBase {
    public TList List { get; private set; }
    public ListHandler(TList List) { this.List = List; }
    public void AddItem(T???? item) { List.ListExample.Add(item); }
}

// Corrected: this will work because TItem can be used to constrain
// the constructed ListBase type as well:
public class ListHandler<TItem> where TItem : ItemBase {
    public ListBase<TItem> List { get; private set; }
    public ListHandler(ListBase<TItem> List) { this.List = List; }
    public void AddItem(TItem item) { List.ListExample.Add(item); }
}

// And this will work just fine:
var handler = new ListHandler<FooItem>(new FooList());

Upvotes: 0

SLaks
SLaks

Reputation: 887215

A ListBase<ItemBase> is not the same as a ListBase<FooItem>.
In particular, you can add any kind of ItemBase to a ListBase<ItemBase>.

You need to accept two generic parameters:

public class ListHandler<TList, TItem> where T : ListBase<TItem> where TItem : ItemBase { }

Upvotes: 4

Related Questions