按基类属性筛选派生类

时间:2015-10-06 21:29:31

标签: c# .net inheritance c#-4.0 covariance

我有两个共享基类(汽车)的班级(汽车/卡车)。我想通过他们的基类汽车上的一个属性过滤汽车和卡车的集合。下面的代码会导致错误:

Cannot implicitly convert type   
'System.Collections.Generic.List<Example.Program.Automobile>' to    
'System.Collections.Generic.List<Example.Program.Car>'
Program.cs    48  27  Example

是否可以通过基类属性进行过滤而无需将结果转换回适当的派生类?

class Program
{
    public class Automobile
    {
        public string Manufacturer { get; set; }

        public static  IEnumerable<Automobile> GetByManufacturer(IEnumerable<Automobile> items, string manufacturer)
        {
            return items.Where(o => o.Manufacturer == manufacturer);
        }
    }

    public class Car : Automobile
    {
        public int TrunkSize { get; set; }
    }

    public class Truck : Automobile
    {
        public int BedSize  { get; set; }
    }

    static void Main(string[] args)
    {

        var cars = new List<Car> 
        {
            new Car { Manufacturer = "Toyota", TrunkSize = 100 },
            new Car { Manufacturer = "Kia", TrunkSize = 70 }
        };

        var trucks = new List<Truck> 
        {
            new Truck { Manufacturer = "Toyota", BedSize = 400 },
            new Truck { Manufacturer = "Dodge", BedSize = 500 }
        };

        // Problem: Get a list of Type Car and a List of Tpye Truck, 
        // where each List contains only cars manufactured by Toyota
        var mfr =  "Toyota";

        List<Car> toyotaCars = Automobile.GetByManufacturer(cars, mfr).ToList();
        List<Car> toyotaTrucks = Automobile.GetByManufacturer(trucks, mfr).ToList();

        Console.WriteLine(toyotaCars.First().GetType().Name);
        Console.WriteLine(toyotaTrucks.First().GetType().Name);
    }
}

1 个答案:

答案 0 :(得分:4)

您可以将定义更改为

public static IEnumerable<TAuto> GetByManufacturer(IEnumerable<TAuto> items, string manufacturer)
                    where TAuto : Automobile
{
    return items.Where(o => o.Manufacturer == manufacturer);
}

现在您返回IEnumerable<Automobile>,然后致电ToList,将其转换为List<Automobile>,然后尝试将其投放到List<Car>,这是不合法的,因为列表可以包含不是Automobile的{​​{1}}。

根据更改,您将返回Car,这可以完全转换为IEnumerable<Car>

此外,第二次通话中的返回类型应为List<Car>,而不是List<Truck>

List<Car>