Monday, March 28, 2011

How to handle this c# generics problem ?

I have a base class that inherits List<> which has multiple classes derived from it.

I want to create a method that can add items to any class that has inherited from this base class, is this possible ?

pseudo code:

public class BaseList<T> : List<T> where T: baseItem
{
}

public BaseList<T> AddItems<T>(int someArg) where T: new(), baseItem
{

BaseList<T> temp = new BaseList<T>();
temp.add(new T());
temp.add(new T());
return temp;
} 

public class MyDerived: BaseList<SomeClass>
{
}

Then to call this code:

MyDerived temp = (MyDerived)AddItems();

is something like this possible ? I can't figure out the correct syntax

From stackoverflow
  • Do you really need to derive from List<T> instead of using composition?

    It sounds like you want a static method in a non-generic type:

    public static TList CreateList<TList,TItem>(int someArg)
        where TList : BaseList<TItem>, new()
        where TItem : baseItem, new()
    {
        TList temp = new TList();
        temp.Add(new TItem());
        temp.Add(new TItem());
        return temp;
    }
    

    It doesn't seem particularly nice though... perhaps if you explained the purpose of this, we could come up with a better idea.

    configurator : There's an error in your code; fix it to TList temp = new TList();
  • You could also use

    public static void AddItems<T>(List<T> list, int someArg) where T: new() {
        list.Add(new T());
        list.Add(new T());
    }
    

    And call it like so:

    List list = new List<SomeClass>();
    AddItems(list, someArg);
    
  • I can't really understand your question but I have run into this problem before. If you ran into the same problem as me: you don't know the <T> parameter at compile time. Fortunately, this is a cynch to solve using interfaces - you can create a stronger type binding by using a non-generic interface.

    class Program
    {
        static void Main(string[] args)
        {
            IAddBaseItem addItem = new DerivedList();
            BaseItem item = new DerivedItem();
            IgnorantMethod(addItem, item);
        }
    
        static void IgnorantMethod(IAddBaseItem list, BaseItem item)
        {
            list.Add(item);
        }
    }
    
    class BaseItem
    {
    }
    
    class BaseList<T> : List<T>, IAddBaseItem
    {
        #region IAddBaseItem Members
    
        void IAddBaseItem.Add(BaseItem item)
        {
            if (item == null)
                Add(item);
            else
            {
                T typedItem = item as T;
                // If the 'as' operation fails the item isn't
                // of type T.
                if (typedItem == null)
                    throw new ArgumentOutOfRangeException("T", "Wrong type");
                Add(typedItem);
            }
        }
    
        #endregion
    }
    
    class DerivedList : BaseList<DerivedItem>
    {
    }
    
    class DerivedItem : BaseItem
    {
    }
    
    interface IAddBaseItem
    {
        void Add(BaseItem item);
    }
    

    As I said, this is my best guess as to what you are asking.

0 comments:

Post a Comment