tags:

views:

4226

answers:

4

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.)

+6  A: 

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>();
}
Daniel Schaffer
I think this gets more at the spirit of what i understand the questioner to be asking (the interface version). Basically its a list of "partially known" items, but more than just "List<object>"
ee
Thanks for the help. So stackoverflow lets me edit my question...but is there any way to combine your answer with those below that add extra information about the impossibility of what I want in C#?
errcw
@errcw I can edit it, or anytone else with 2k+ rep can... what specific info did you want?
Daniel Schaffer
Simply the technical note on C# 3/4 from Mehrdad: "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."
errcw
+1  A: 

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.

Mehrdad Afshari
A: 

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

Reed Copsey
+1  A: 

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>>();
      List<SomeClass<T>> l = (List<SomeClass<T>>)list[type];
      l.Add(item);
     }

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

test it with the following:

    class Program
    {
     static void Main(string[] args)
     {
      C c = new C();
      SomeClass<int> sc1 = new SomeClass<int>();
      SomeClass<String> sc2 = new SomeClass<String>();
      c.Method(sc1);
      c.Method(sc2);
      c.Method(sc1);
      c.Method(sc2);
     }
    }
Dan