10

I'm aware that C# doesn't have generic wildcards, and that a similar effect can be achieved by generic methods, but I need to use a wildcard in a field and can't work out if there is any way to encode it.

List<State<Thing>> list;

void AddToList<T>() where T : Thing {
    list.Add(new State<T>());
}

Of course, this doesn't work because the object being added isn't of type State<Thing>, it's of type State<T> where T : Thing. Is it possible to adjust the most internal type of the list to be the Java equivalent of ? extends Thing rather than just Thing?

abatishchev
  • 98,240
  • 88
  • 296
  • 433
zmthy
  • 568
  • 3
  • 13

3 Answers3

4

Note that C# 4 does have additional variance support, but it does not apply in the List<T> case, for various reasons (has both "in" and "out" methods, and is a class).

I think, however, the way to address this is with something like:

interface IState { // non-generic
    object Value { get; } // or whatever `State<Thing>` needs
}
class State<T> : IState {
    public T Value { get { ...} } // or whatever
    object IState.Value { get { return Value; } }
}

and

List<IState> list; ...

which will then allow you to add any State<T>. It doesn't really use much of the T, and a cast would be needed to get from the object to T, but .... it will at least work.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • I really don't understand why can't I cast as the following: `(State)new State` while `T : Thing`! But can `(Thing)new T()` – abatishchev Dec 08 '11 at 07:23
  • 3
    @abatishchev because a `SomeSpecificThing` **is** a `Thing`; but it is *not* true that a `State` is a `State`. There is no inheritance etc. If it were a generic interface, if **could** potentially be `IState`, in which case the 4.0 variance rules start to apply, and **then** yes, there is a cast from `IState` to `IState`. – Marc Gravell Dec 08 '11 at 07:27
3

You could try something like this :

    interface IState<out T> { }
    class State<T> : IState<T> { }
    class Thing {}

    List<IState<Thing>> list;

    void AddToList<T>() where T : Thing
    {
        list.Add(new State<T>());
    }
Poca
  • 41
  • 4
0

Declare your list as the following:

class State<T> where T : Thing
{
    ...

    List<State<T>> list = new List<State<T>>();
    // or
    public class StateList<T> : List<State<T>>
    {
         void AddToList(T item);
    }
}

then compiler will be able to convert.

abatishchev
  • 98,240
  • 88
  • 296
  • 433