tags:

views:

104

answers:

2

I have an interface list which stores a variety of objects derived from that interface. I would like to write a function where the caller specifies the type to extract. I've tried this:

List<IParts> PartList;

...

public List<IPart> Fetch(Type PartType)
{
   return this.PartList.OfType<PartType>().Cast<IPart>().ToList();
}

But it doesn't like a passed type. Any suggestions?

+2  A: 

Specify it as a type parameter instead:

public List<IPart> Fetch<T>() where T : IPart
{
    return this.PartList.OfType<T>().Cast<IPart>().ToList();
}

You'd call it like this:

List<IPart> foo = parts.Fetch<Exhaust>();

That's fine if you know the part type at compile-time. If you don't, you'll need to use reflection to basically get the OfType() method in Enumerable<T> and create the write generic method from it. Something like:

private static readonly MethodInfo OfTypeMethod = 
    typeof(Enumerable).GetMethod("OfType");

public List<IPart> Fetch(Type partType)
{
    MethodInfo method = OfTypeMethod.MakeGenericMethod(partType);
    IEnumerable enumerable = (IEnumerable) method.Invoke
        (null, new object[] { PartList });
    return enumerable.Cast<IPart>().ToList();
}
Jon Skeet
You can add a "where T : IPart" generic restriction that'll make it so you're not getting invalid casts and logic errors
Thomas G. Mayfield
Ooh, nice - will do.
Jon Skeet
+2  A: 

If you have to support various types at runtime (rather than at compile time with generics):

public List<IPart> Fetch(Type PartType)
{
    if (!typeof(IPart).IsAssignableFrom(PartType))
    {
        throw new ArgumentOutOfRangeException("PartType", "Must derive from IPart");
    }
    return this.PartList.Where(i => i != null && PartType.IsAssignableFrom(i.GetType())).ToList();
}
Thomas G. Mayfield
Nice - certainly a bit simpler than using reflection to get the generic method. Probably more efficient for small lists and less efficient for large lists. You might want to check for nullity before calling i.GetType().
Jon Skeet
There I go assuming input is valid again. :)
Thomas G. Mayfield