Extension method to filter a list of concrete types based on interface?
I have a multiple classes that implement an interface. I want to create an extension method to filter a list of these classes based on a value. Here's a hypothetical example:
public enum Transmission
{
Standard = 1,
Automatic = 2
}
public interface ICar
{
Transmission Tranny { get; set; }
}
public class Car : ICar
{
public Tra开发者_如何学Cnsmission Tranny { get; set; }
public string Make { get;set;}
}
public static class CarExtensions
{
public static List<ICar> OnlyAuto(this List<ICar> cars)
{
return cars.Where(x => x.Tranny == Transmission.Automatic).ToList();
}
}
I want to create an extension method to filter a list of cars...but this one doesn't kick in for
var x = new List<Car>();
x.OnlyAuto <-- compile error...
the extension method doesn't intellisense?
The problem isn't specific to extension methods. Given the definitions from your example the following results in a compiler-error:
void DoStuff(List<ICar> cars)
{
}
DoStuff(new List<Car>());
The problem is that even though the elements of the List<Car>
implement ICar
the type List<Car>
cannot be used in places where a List<ICar>
is expected.
In the example you could use
var x = new List<ICar>();
x.OnlyAuto();
or add the following extension-method:
public static IEnumerable<ICar> OnlyAuto(this IEnumerable<ICar> cars)
{
return cars.Where(x => x.Tranny == Transmission.Automatic).ToList();
}
and use Cast:
var x = new List<Car>();
(x.Cast<ICar>()).OnlyAuto();
If you search google for "C# covariance" you will find that a lot of people has written about this problem. And it seems that in c# 4.0 IEnumerable is covariant, meaning that you can eliminate the use of Cast
in the example above.
精彩评论