C # - how to create an inherited shared collection from a factory method

I am trying to write a factory method that will create a derived instance of an abstract generic collection class. Here are the base classes ...

abstract class ItemBase { }

abstract class CollectionBase<T> : Collection<T> where T : ItemBase, new() { }

      

... and their derived classes ...

class Item : ItemBase { }

class ItemCollection : CollectionBase<Item> {}

      

Now I need a factory method that will create the ItemCollection. But note that the derived classes Item and ItemCollection are unknown to the class that contains this factory method. This is how I imagine what it should be ...

static T CreateItemCollection<T>() where T : CollectionBase<ItemBase>, new()
{
    return new T();
}

      

... and I'm guessing I'm referencing it this way ...

var collection = CreateItemCollection<ItemCollection>();

      

But the factory method won't compile because ItemBase must have a parameterless constructor. And the call of the invokation refuses to believe what is ItemCollection

received from CollectionBase<ItemBase>

.

Can anyone point me in the right direction? Thank.

+2


source to share


2 answers


ItemCollection

is not deduced from CollectionBase<ItemBase>

due to general invariance. After all, you can add ItemBase

in CollectionBase<ItemBase>

, but you don't want that for ItemCollection

!

You need to make the method generic in two types of parameters:

static T CreateItemCollection<TCollection, TItem>()
    where TCollection : CollectionBase<TItem>, new()
    where TItem : ItemBase
{
    return new TCollection();
}

      



Only the collection type needs a parameterless constructor. You would call it with:

var collection = CreateItemCollection<ItemCollection, Item>();

      

+6


source


The problem here is general constraints, in C # 3.0, has any leeway with respect to variance. The compliance is pretty strict. Since ItemCollection is derived from CollectionBase<Item>

, it is not considered to derive from , CollectionBase<ItemBase>

although the types may appear to be compatible.



+3


source