tags:

views:

89

answers:

4

I'm trying the following design without success:

abstract class Foo<T>
{
    abstract T Output { get; }
}

class Bar
{
    List<Foo> Foos;
}

I would dislike using an array list, because I would have to use unsafe casts to get the type. I'd like Foo to be typed so that "Output" isn't just an object, in which case I'd have to use unsafe casts as well.

As my code is at the moment, I use Foo untyped with Output as an object.

A: 

You're very close - you just missed another generic specification:

abstract class Foo<T>
{
    abstract T Output { get; }
}

class Bar
{
    List<Foo<string>> Foos; //here we specified that Foo is of strings
}
veljkoz
I think he knows that. This is not what he meant.
Timwi
A: 

List<Foo> is invalid since Foo is a template and needs a class specified, even if it's a generic itself again (List<Foo<U> >).

Ignacio Vazquez-Abrams
generics are not templates...
Thomas Levesque
This would be it. Make Bar generic (the type parameter can be T as well, or U, or whatever) and use the type parameter to keep Foo open. You can do this as far up the container hierarchy as you have control; however, at some point you will have to close the generic implementation with a concrete type in order to consume the class(es). If you want to do that dynamically, you can use reflection to instantiate a generic object closed to a type identified by a Type object or a string, but this can get messy real quick.
KeithS
+1  A: 

No you cannot use a generic in such a manner. You need either add a generic type parameter to Bar and forward it to Foo<T> or provide a closed instance of Foo<T> in the Bar type.

Example of the first

class Bar<T> {
  public List<Foo<T>> Foos;
}
JaredPar
I think he knows that. This is not what he meant.
Timwi
@Timwi, then the OP should be more clear in the question. When faced with an ambiguous question it's very easy to give an incorrect answer. The downvote for me and others is unwarranted. By your logic I should downvote you for having a different interpretation than me.
JaredPar
I agree, I find such ambiguous questions annoying too. It is all too easy to assume that one’s own interpretation is right — sorry about that! (Of course it would help if @Lazlo shed some light on this...) (GameZelda seems to agree with me, though :) )
Timwi
Sorry for being unclear, although I can't interpret why JaredPar might have thought I needed to know that. My question indeed is how Timwi interpreted it.
Lazlo
+3  A: 

If I understand you correctly, you want a list of Foo objects which have different types of Outputs, right? Since these outputs are of different types, you would have to use casts here anyway.

However, the following idea might help. How about you declare a non-generic interface called IFoo: ¹

public interface IFoo
{
    object Output { get; }
}

and then implement it in your abstract class:

abstract class Foo<T> : IFoo
{
    abstract T Output { get; }
    object IFoo.Output { get { return Output; } }
}

Then you can declare a list of IFoos:

class Bar
{
    List<IFoo> Foos;
}

When accessing those foos, you can either retrieve the output as an object via the interface:

var myObject = Foos[0].Output;     // type ‘object’

or you can try to discover the real type if you know that it can only be one of a few specific types:

if (Foos[0] is Foo<string>)
    var myString = ((Foo<string>) Foos[0]).Output;   // type ‘string’

You can even do filtering based on the type, for example:

// Type ‘IEnumerable<string>’ (rather than ‘IEnumerable<object>’)!
var stringFoos = Foos.OfType<Foo<string>>().Select(f => f.Output);

¹ You can also make this an abstract base class called Foo and have Foo<T> derive from it. In that case, you would need to mark Foo<T>.Output with the new keyword and use base.Output to access the abstract base member.

Timwi
Thanks. :) Exactly what I was looking for.
Lazlo