Метод расширения для фильтрации списка конкретных типов на основе интерфейса? - PullRequest
1 голос
/ 24 февраля 2010

У меня есть несколько классов, которые реализуют интерфейс. Я хочу создать метод расширения для фильтрации списка этих классов на основе значения. Вот гипотетический пример:

public enum Transmission
{ 
    Standard = 1,
    Automatic = 2
}

public interface ICar
{
    Transmission Tranny { get; set; }
}

public class Car : ICar
{
    public Transmission 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();
    }
}

Я хочу создать метод расширения для фильтрации списка автомобилей ... но этот метод не срабатывает для

var x = new List<Car>();
x.OnlyAuto <-- compile error...

метод расширения не имеет смысла?

1 Ответ

3 голосов
/ 06 марта 2010

Проблема не связана с методами расширения. Учитывая определения из вашего примера, следующие ошибки приводят к ошибке компилятора:

void DoStuff(List<ICar> cars)
{
}

DoStuff(new List<Car>());

Проблема в том, что, хотя элементы List<Car> реализуют ICar, тип List<Car> нельзя использовать в местах, где ожидается List<ICar>.

В примере вы можете использовать

var x = new List<ICar>(); 
x.OnlyAuto();

или добавьте следующий метод расширения:

public static IEnumerable<ICar> OnlyAuto(this IEnumerable<ICar> cars)
{
   return cars.Where(x => x.Tranny == Transmission.Automatic).ToList();
}

и используйте Cast:

var x = new List<Car>();
(x.Cast<ICar>()).OnlyAuto();

Если вы ищете в Google "C # covariance", вы обнаружите, что многие люди писали об этой проблеме. И кажется, что в c # 4.0 IEnumerable является ковариантным, что означает, что вы можете исключить использование Cast в приведенном выше примере.

...