Is it possible to use a list of untyped generics in C#?
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.
If I understand you correctly, you want a list of Foo
objects which have different types of Output
s, 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 IFoo
s:
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.
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> >
).
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;
}
精彩评论