Question

I am using a hierarchy of generic collection classes that derive from an abstract base class to store entity items that also derive from an abstract base class:

abstract class ItemBase { }

class MyItem : ItemBase
{
    public MyItem()
    {
    }
}


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

class MyCollection : CollectionBase<MyItem> { }

The objectives of this model are to enforce strict type discipline on the members of any class derived from CollectionBase<T> and to guarantee that these members have a default public constructor. Thus far it works.

Now I want to create a factory method that returns an instance of a class derived from CollectionBase<T>. I understand that the usual approach would be:

public CollectionBase<T> CreateCollection<T>();

... or maybe ...

public T Create CreateCollection<T>();

However, the problem is that the calling routine does not know what "T" is required. It is the factory method itself that must determine the specific type of collection to return. So I need a non-generic method signature that says "the return type will derive from CollectionBase<T>". I envisage something like this (if it were legal) ...

public CollectionBase<> CreateCollection();

I assume this is another of those thorny generic variance issues, but even after reading Eric Lippert's extensive explanation on the subject, I am still unclear whether what I am trying to do is likely to be feasible in C# 4.0, and whether there is a simple workaround in C# 3.0.

Thanks in advance for your ideas.

Was it helpful?

Solution

Let's say the factory method were creating a single item. You would have:

public ItemBase CreateItem();

You have to use ItemBase because you can't know anything more specific. Applying that principle to the collection method, you get:

public CollectionBase<ItemBase> CreateCollection();

Due to lack of variance, you need an adapter class which derives from CollectionBase<ItemBase> and wraps the actual collection which is created.

In C# 4.0 you would just return the actual collection.

Edit: The factory might look like this, with the adapter embedded:

public class CollectionFactory
{
    public CollectionBase<ItemBase> CreateCollection()
    {
        if(someCondition)
        {
            return CreateAdapter(new MyCollection());
        }
        else
        {
            return CreateAdapter(new MyOtherCollection());
        }
    }

    private static CollectionAdapter<T> CreateAdapter<T>(CollectionBase<T> collection) where T : ItemBase, new()
    {
        return new CollectionAdapter<T>(collection);
    }

    private class CollectionAdapter<T> : CollectionBase<ItemBase> where T : ItemBase, new()
    {
        private CollectionBase<T> _collection;

        internal CollectionAdapter(CollectionBase<T> collection)
        {
            _collection = collection;
        }

        // Implement CollectionBase API by passing through to _collection
    }
}

OTHER TIPS

Probably what you need is:

public CollectionBase<Object> CreateCollection();

Since every class directly or indirectly inherits from the Object class.

I haven't actually done this, and apologies if it's completely naive, but...

public CollectionBase<Object> CreateCollection();

?

If you really want it to be anything, you could just return ICollection, and then your consumers could call the .Cast<ItemBase>() extension method as they need.

From what I understand, in .NET 4.0 you would be able to return CollectionBase<ItemBase>, but I haven't tried it on the Beta yet.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top