Question

Problem description

I am trying to store a collection of generic Foo<T> elements, where T may be different for each item. I also have functions like DoSomething<T>(Foo<T>) that can accept a Foo<T> of any T. It seems like I should be able to call this function on each element of the abovementioned list, because they are all valid parameters for the function, but I can't seem to express this idea to the C# compiler.

The problem, as far as I can tell, is that I can't really express a list like that, because C# does not allow me to write Foo<T> without binding T. What I would want is something like Java's wildcard mechanism (Foo<?>). Here is how it might look in a Pseudo-C#, where this wildcard type existed:

class Foo<T> {
    // ...
}

static class Functions {
    public static void DoSomething<T>(Foo<T> foo) {
        // ...
    }

    public static void DoSomething(List<Foo<?>> list) {
        foreach(Foo<?> item in list)
            DoSomething(item);
    }
}

This pattern is valid in Java, but how can I do the same in C#? I have experimented a bit to find solutions which I'll post in an answer below, but I feel that there should be a better way.

Note: I have already solved this problem "well enough" for my practical needs, and I know ways to work around it (e.g. using the dynamic type), but I'd really like to see if there is a simpler solution that does not abandon static type safety.

Just using object or a nongeneric supertype, as has been suggested below, does not allow me to call functions that require a Foo<T>. However, this can be sensible even if I don't know anything about T. For example, I could use the Foo<T> to retrieve a List<T> list from somewhere, and a T value from somewhere else, and then call list.Add(value) and the compiler will know that all the types work out right.

Motivation

I was asked why I would ever need something like this, so I'm making up an example that is a bit closer to the everyday experience of most developers. Imagine that you are writing a bunch of UI components which allow the user to manipulate values of a certain type:

public interface IUiComponent<T> {
    T Value { get; set; }
}

public class TextBox : IUiComponent<string> {
    public string Value { get; set; }
}

public class DatePicker : IUiComponent<DateTime> {
    public DateTime Value { get; set; }
}

Apart from the Value property, the components will have have many other members of course (e.g. OnChange events).

Now let's add an undo system. We shouldn't have to modify the UI elements themselves for this, because we have access to all the relevant data already--Just hook up the OnChange events and whenever the user changes a UI component, we store away the value of each IUiComponent<T> (A bit wasteful, but let's keep things simple). To store the values we will use a Stack<T> for each IUiComponent<T> in our form. Those lists are accessed by using the IUiComponent<T> as key. I'll leave out the details of how the lists are stored (If you think this matters I'll provide an implementation).

public class UndoEnabledForm {
    public Stack<T> GetUndoStack<T>(IUiComponent<T> component) {
        // Implementation left as an exercise to the reader :P
    }

    // Undo for ONE element. Note that this works and is typesafe,
    // even though we don't know anything about T...
    private void Undo<T>(IUiComponent<T> component) {
        component.Value = GetHistory(component).Pop();
    }
    
    // ...but how do we implement undoing ALL components?
    // Using Pseudo-C# once more:
    public void Undo(List<IUiComponent<?>> components) {
        foreach(IUiComponent<?> component in components)
            Undo(component);
    }
}

We could undo everything by directly calling Undo<T>() on all the IUiComponents (by name):

public void Undo(List<IUiComponent<?>> components) {
    Undo(m_TextBox);
    Undo(m_DatePicker);
    // ...
}

However, I want to avoid this, because it means you will have to touch one more place in the code if you add/remove a component. If you have tens of fields and more functions that you want to perform on all the components (e.g. write all their values to a database and retrieve them again), this can become a lot of duplication.

Sample Code

Here is a small piece of code that you can use to develop/check a solution. The task is to put several Pair<T>-objects into some kind of collection object, and then call a function which accepts this collection object and swaps the First and Second field of each Pair<T> (using Application.Swap()). Ideally, you should not use any casts or reflection. Bonus points if you can manage to do it without modifying the Pair<T>-class in any way :)

class Pair<T> {
    public T First, Second;

    public override string ToString() {
        return String.Format("({0},{1})", First, Second);
    }    
}

static class Application {
    static void Swap<T>(Pair<T> pair) {
        T temp = pair.First;
        pair.First = pair.Second;
        pair.Second = temp;
    }

    static void Main() {
        Pair<int> pair1 = new Pair<int> { First = 1, Second = 2 };
        Pair<string> pair2 = new Pair<string> { First = "first", Second = "second" };
        // imagine more pairs here

        // Silly solution
        Swap(pair1);
        Swap(pair2);

        // Check result
        Console.WriteLine(pair1);
        Console.WriteLine(pair2);
        Console.ReadLine();
    }
}
Was it helpful?

Solution 4

For those who may still find this interesting, here is the best solution I could come up with that also meets the "bonus requirement" of not touching the original type in any way. It is basically a Visitor pattern with the twist that we don't store the Foo<T> directly in our container, but rather store a delegate which calls an IFooVisitor on our Foo<T>. Notice how we can easily make a list of those because T is not actually part of the delegates' type.

// The original type, unmodified
class Pair<T> {
    public T First, Second;
}

// Interface for any Action on a Pair<T>
interface IPairVisitor {
    void Visit<T>(Pair<T> pair);
}

class PairSwapVisitor : IPairVisitor {
    public void Visit<T>(Pair<T> pair) {
        Application.Swap(pair);
    }
}

class PairPrintVisitor : IPairVisitor {
    public void Visit<T>(Pair<T> pair) {
        Console.WriteLine("Pair<{0}>: ({1},{2})", typeof(T), pair.First, pair.Second);
    }
}

// General interface for a container that follows the Visitor pattern
interface IVisitableContainer<T> {
    void Accept(T visitor);
}

// The implementation of our Pair-Container
class VisitablePairList : IVisitableContainer<IPairVisitor> {
    private List<Action<IPairVisitor>> m_visitables = new List<Action<IPairVisitor>>();

    public void Add<T>(Pair<T> pair) {
        m_visitables.Add(visitor => visitor.Visit(pair));
    }

    public void Accept(IPairVisitor visitor) {
        foreach (Action<IPairVisitor> visitable in m_visitables)
            visitable(visitor);
    }
}

static class Application {
    public static void Swap<T>(Pair<T> pair) {
        T temp = pair.First;
        pair.First = pair.Second;
        pair.Second = temp;
    }

    static void Main() {
        VisitablePairList list = new VisitablePairList();
        list.Add(new Pair<int> { First = 1, Second = 2 });
        list.Add(new Pair<string> { First = "first", Second = "second" });

        list.Accept(new PairSwapVisitor());
        list.Accept(new PairPrintVisitor());
        Console.ReadLine();
    }
}

Output:

Pair<System.Int32>: (2,1)
Pair<System.String>: (second,first)

OTHER TIPS

I would suggest you define an interface to invoke the functions you'll want to call as DoSomething<T>(T param). In simplest form:

public interface IDoSomething
  { void DoSomething<T>(T param); }

Next define a base type ElementThatCanDoSomething:

abstract public class ElementThatCanDoSomething
  { abstract public void DoIt(IDoSomething action); }

and a generic concrete type:

public class ElementThatCanDoSomething><T>
{
  T data;
  ElementThatCanDoSomething(T dat) { data = dat; }

  override public void DoIt(IDoSomething action)
    { action.DoIt<T>(data); }
}

Now it's possible to construct an element for any type compile-time T, and pass that element to a generic method, keeping type T (even if the element is null, or if the element is of a derivative of T). The exact implementation above isn't terribly useful, but it can be easily extended in many useful ways. For example, if type T had generic constraints in the interface and concrete type, the elements could be passed to methods which had those constraints on its parameter type (something which is otherwise very difficult, even with Reflection). It may also be useful to add versions of the interface and invoker methods that can accept pass-through parameters:

public interface IDoSomething<TX1>
{ void DoSomething<T>(T param, ref TX1 xparam1); }

... and within the ElementThatCanToSomething

  abstract public void DoIt<TX1>(IDoSomething<TX1> action, ref TX1 xparam1);

... and within the ElementThatCanToSomething<T>

  override public void DoIt<TX1>(IDoSomething<TX1> action, ref TX1 xparam1)
    { action.DoIt<T>(data, ref xparam1); }

The pattern may easily be extended to any number of pass-through parameters.

EDIT 2: in the case of your overhauled question, the approach is basically the same I've proposed you earlier. Here I'm adapting it to your scenario and commenting better on what makes it work (plus an unfortunate "gotcha" with value types...)

// note how IPair<T> is covariant with T (the "out" keyword)
public interface IPair<out T> {
     T First {get;}
     T Second {get;}
}

// I get no bonus points... I've had to touch Pair to add the interface
// note that you can't make classes covariant or contravariant, so I 
// could not just declare Pair<out T> but had to do it through the interface
public class Pair<T> : IPair<T> {
    public T First {get; set;}
    public T Second {get; set;}

    // overriding ToString is not strictly needed... 
    // it's just to "prettify" the output of Console.WriteLine
    public override string ToString() {
        return String.Format("({0},{1})", First, Second); 
    }    
}

public static class Application {
    // Swap now works with IPairs, but is fully generic, type safe
    // and contains no casts      
    public static IPair<T> Swap<T>(IPair<T> pair) {
        return new Pair<T>{First=pair.Second, Second=pair.First};       
    }

    // as IPair is immutable, it can only swapped in place by 
    // creating a new one and assigning it to a ref
    public static void SwapInPlace<T>(ref IPair<T> pair) {
        pair = new Pair<T>{First=pair.Second, Second=pair.First};
    }

    // now SwapAll works, but only with Array, not with List 
    // (my understanding is that while the Array's indexer returns
    // a reference to the actual element, List's indexer only returns
    // a copy of its value, so it can't be switched in place
    public static void SwapAll(IPair<object>[] pairs) {
        for(int i=0; i < pairs.Length; i++) {
           SwapInPlace(ref pairs[i]);
        }
    }
}

That's more or less it... Now in your main you can do:

var pairs = new IPair<object>[] {
    new Pair<string>{First="a", Second="b"},
    new Pair<Uri> {
               First=new Uri("http://www.site1.com"), 
               Second=new Uri("http://www.site2.com")},     
    new Pair<object>{First=1, Second=2}     
};

Application.SwapAll(pairs);
foreach(var p in pairs) Console.WriteLine(p.ToString());

OUTPUT:

(b,a)
(http://www.site2.com/,http://www.site1.com/)
(2,1)

So, your Array is type-safe, because it can only contain Pairs (well, IPairs). The only gotcha is with value types. As you can see I had to declare the last element of the array as a Pair<object> instead of Pair<int> as I would have liked. This is because covariance/contravariance don't work with value types so I had to box int in an object.

=========

EDIT 1 (old, just leaving there as reference to make sense of the comments below): you could have both a non-generic marker interface for when you need to act on the container (but don't care about the "wrapped" type) and a covariant generic one for when you need the type information.

Something like:

interface IFoo {}
interface IFoo<out T> : IFoo {
    T Value {get;}
}

class Foo<T> : IFoo<T> {
    readonly T _value;
    public Foo(T value) {this._value=value;}
    public T Value {get {return _value;}}
}

Suppose you have this simple hierarchy of classes:

public class Person 
{
    public virtual string Name {get {return "anonymous";}}
}

public class Paolo : Person 
{
    public override string Name {get {return "Paolo";}}
}

you could have functions that work either on any IFoo (when you don't care if Foo wraps a Person) or specifically on IFoo<Person> (when you do care): e.g.

static class Functions 
{
    // this is where you would do DoSomethingWithContainer(IFoo<?> foo)
    // with hypothetical java-like wildcards 
    public static void DoSomethingWithContainer(IFoo foo) 
    {
        Console.WriteLine(foo.GetType().ToString());
    }

    public static void DoSomethingWithGenericContainer<T>(IFoo<T> el) 
    {
        Console.WriteLine(el.Value.GetType().ToString());
    }

    public static void DoSomethingWithContent(IFoo<Person> el) 
    {
        Console.WriteLine(el.Value.Name);
    }

}

which you could use like this:

    // note that IFoo can be covariant, but Foo can't,
    // so we need a List<IFoo  
    var lst = new List<IFoo<Person>>
    {   
        new Foo<Person>(new Person()),
        new Foo<Paolo>(new Paolo())
    };


    foreach(var p in lst) Functions.DoSomethingWithContainer(p);    
    foreach(var p in lst) Functions.DoSomethingWithGenericContainer<Person>(p);
    foreach(var p in lst) Functions.DoSomethingWithContent(p);
// OUTPUT (LinqPad)
// UserQuery+Foo`1[UserQuery+Person]
// UserQuery+Foo`1[UserQuery+Paolo]
// UserQuery+Person
// UserQuery+Paolo
// anonymous
// Paolo

One notable thing in the output is that even the function that only received IFoo still had and printed the full type information which in java would have been lost with type erasure.

It seems that in C#, you have to create a list of Foo, which you use as base type of Foo<T>. However, you can't easily get back to Foo<T> from there.

One solution I found is to add an abstract method to Foo for each function SomeFn<T>(Foo<T>), and implement them in Foo<T> by calling SomeFn(this). However, that would mean that every time you want to define a new (external) function on Foo<T>, you have to add a forwarding function to Foo, even though it really shouldn't have to know about that function:

abstract class Foo {
    public abstract void DoSomething();
}

class Foo<T> : Foo {
    public override void DoSomething() {
        Functions.DoSomething(this);
    }
    // ...
}

static class Functions {
    public static void DoSomething<T>(Foo<T> foo) {
        // ...
    }

    public static void DoSomething(List<Foo> list) {
        foreach(Foo item in list)
            item.DoSomething();
    }
}

A slightly cleaner solution from a design perspective seems to be a Visitor pattern which generalizes the above approach to a degree and severs the coupling between Foo and the specific generic functions, but that makes the whole thing even more verbose and complicated.

interface IFooVisitor {
    void Visit<T>(Foo<T> foo);
}

class DoSomethingFooVisitor : IFooVisitor {
    public void Visit<T>(Foo<T> foo) {
        // ...
    }
}

abstract class Foo {
    public abstract void Accept(IFooVisitor foo);
}

class Foo<T> : Foo {
    public override void Accept(IFooVisitor foo) {
        foo.Visit(this);
    }
    // ...
}

static class Functions {
    public static void DoSomething(List<Foo> list) {
        IFooVisitor visitor = new DoSomethingFooVisitor();
        foreach (Foo item in list)
            item.Accept(visitor);
    }
}

This would almost be a good solution IMO, if it was easier to create a Visitor. Since C# apparently does not allow generic delegates/lambdas, you cannot specify the visitor inline and take advantage of closures though - As far as I can tell, each Visitor needs to be a new explicitly defined class with possible extra parameters as fields. The Foo type also has to explicitly support this scheme by implementing the Visitor pattern.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top