Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding generic object to generic list in C#

Tags:

c#

list

generics

I have class where the relevant part looks like

class C {
    void Method<T>(SomeClass<T> obj) {
        list.Add(obj);
    }
    List<?> list = new List<?>();
}

How should I define the list so that the class compiles?

I want a list of type List<SomeClass<?>>, that is a list of objects of SomeClass where each object can have any type parameter. The Java ? construct allows this; what is the C# equivalent? If no such thing exists, is there a suitable workaround? (A List<object> would do but is terribly ugly.)

like image 448
errcw Avatar asked Apr 16 '09 00:04

errcw


People also ask

How do you add an object to a generic list?

To do what you want, you have two options. You can use List<object>, and handle objects. This will not be typesafe, and will have boxing/unboxing issues for value types, but it will work. Your other option is to use a generic constraint to limit to a base class or interface, and use a List<Interface>.

Can you create a generic object?

The principle difference is that a generic type has a list of Type objects representing its generic type parameters. The first procedure in this section examines generic types. You can create a Type object that represents a constructed type by binding type arguments to the type parameters of a generic type definition.

Can we have non generic method in generic class C#?

Yes, There are two level where you can apply generic type . You can apply generic type on Method level as well as Class level (both are optional). As above example you applied generic type at method level so, you must apply generic on method return type and method name as well. You need to change a bit of code.

What is generic object in C#?

A generic in C# is a type that uses objects of a different type. Said different type is not specified until an instance of the generic object is created. We can identify a generic type by looking for the syntax <T> , where T is a placeholder that represents the type being used by the generic.


4 Answers

I don't think you can do this in C#... you would have to add the type parameter to the class:

class C<T> {
    void Method(SomeClass<T> obj) {
        list.Add(obj);
    }
    List<SomeClass<T>> list = new List<SomeClass<T>>();
}

The other option would be to use an interface:

class C {

    void Method<T>(T obj)
         where T : ISomeClass {
        list.Add(obj);
    }
    List<ISomeClass> list = new List<ISomeClass>();
}
like image 179
Daniel Schaffer Avatar answered Oct 02 '22 07:10

Daniel Schaffer


To do what you want, you have two options.

You can use List<object>, and handle objects. This will not be typesafe, and will have boxing/unboxing issues for value types, but it will work.

Your other option is to use a generic constraint to limit to a base class or interface, and use a List<Interface>.

like image 27
Reed Copsey Avatar answered Oct 02 '22 08:10

Reed Copsey


Unfortunately, there is no direct equivalent in C# 3.0 as generics are invariant. You'll be able to do something like this in a graceful manner using C# 4.0 safe co/contra-variance feature. To workaround it, you could inherit SomeClass<T> from a nongeneric base and create a List<BaseClass> instead. If each instance of the class should hold only one type, you could make the class itself generic and set the type parameter there.

like image 35
mmx Avatar answered Oct 02 '22 09:10

mmx


I don't know anything about Java's ? construct, but I think the following most closely preserves your existing syntax while also matching your description.

    class SomeClass<T>
    {
    }

    class C
    {
        void Add<T>(SomeClass<T> item)
        {
            Type type = typeof(SomeClass<T>);
            if (!list.ContainsKey(type))
                list[type] = new List<SomeClass<T>>();
            var l = (List<SomeClass<T>>)list[type];
            l.Add(item);
        }

        public void Method<T>(SomeClass<T> obj)
        {
            Add(obj);
        }
        readonly Dictionary<Type, object> list = new Dictionary<Type, object>();
    }

test it with the following:

    class Program
    {
        static void Main(string[] args)
        {
            var c = new C();
            var sc1 = new SomeClass<int>();
            var sc2 = new SomeClass<String>();
            c.Method(sc1);
            c.Method(sc2);
            c.Method(sc1);
            c.Method(sc2);
        }
    }
like image 44
Ðаn Avatar answered Oct 02 '22 08:10

Ðаn