How to declare a method that returns a generic set of "nothing" (C #)

I use a generic class hierarchy that comes from an abstract base class to store entity elements that also come 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 goals of this model are to provide strong type discipline for the members of any class that derives from CollectionBase <T> and to ensure that these members have a public default constructor. While 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 is:

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

      

... or perhaps ...

public T Create CreateCollection<T>();

      

The problem, however, is that the caller doesn't know what "T" is. It is the factory method that must determine the specific type of the returned collection. Therefore, I need a non-generic method signature that says "The return type will be obtained from CollectionBase <T>". I'm guessing something like this (if it was legal) ...

public CollectionBase<> CreateCollection();

      

I'm guessing this is another one of those tricky type deviation issues, but even after reading Eric Lippert's extensive explanation on the subject, I'm still unclear if what I'm trying to do is possibly in C # 4.0 and is simple workaround in C # 3.0.

Thanks in advance for your ideas.

+2


source to share


4 answers


Let's say the factory method created one item. You would have:

public ItemBase CreateItem();

      

You must use ItemBase

because you cannot know anything more specific. By applying this principle to the collection method, you get:

public CollectionBase<ItemBase> CreateCollection();

      



Due to the lack of variance, you need an adapter class that is derived from CollectionBase<ItemBase>

and wraps around the created collection.

In C # 4.0, you will simply return the actual collection.

Edit: the factory might look like the following inline adapter:

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
    }
}

      

+1


source


You probably need:

public CollectionBase<Object> CreateCollection();

      



Since every class directly or indirectly inherits from the Object.

0


source


I didn't actually do it and I apologize if it's completely naive, but ...

public CollectionBase<Object> CreateCollection();

      

?

0


source


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

as needed.

From what I understand, in .NET 4.0 you can revert CollectionBase<ItemBase>

, but I haven't tried it on beta yet.

0


source







All Articles