C# 将派生类传递给使用父类c的方法#

C# 将派生类传递给使用父类c的方法#,c#,methods,parent,derived,C#,Methods,Parent,Derived,今天我参加了一个测试,任务是在已经编写的代码中添加静态方法getMovingVehicles。我做的就像你在下面看到的那样,但在通过在线编译器后,我可以看到有如下错误: Compilation error (line 28, col 39): The best overloaded method match for 'Rextester.Program.getMovingVehicles(System.Collections.Generic.List<Rextester.Vehicle&g

今天我参加了一个测试,任务是在已经编写的代码中添加静态方法getMovingVehicles。我做的就像你在下面看到的那样,但在通过在线编译器后,我可以看到有如下错误:

Compilation error (line 28, col 39): The best overloaded method match for 'Rextester.Program.getMovingVehicles(System.Collections.Generic.List<Rextester.Vehicle>)' has some invalid arguments
Compilation error (line 28, col 57): Argument 1: cannot convert from 'System.Collections.Generic.List<Rextester.Car>' to 'System.Collections.Generic.List<Rextester.Vehicle>'
Compilation error (line 29, col 41): The best overloaded method match for 'Rextester.Program.getMovingVehicles(System.Collections.Generic.List<Rextester.Vehicle>)' has some invalid arguments
Compilation error (line 29, col 59): Argument 1: cannot convert from 'System.Collections.Generic.List<Rextester.Plane>' to 'System.Collections.Generic.List<Rextester.Vehicle>'
编译错误(第28行,第39列):与“Rextester.Program.getMovingVehicles(System.Collections.Generic.List)”匹配的最佳重载方法具有一些无效参数
编译错误(第28行,第57列):参数1:无法从“System.Collections.Generic.List”转换为“System.Collections.Generic.List”
编译错误(第29行,第41列):与“Rextester.Program.getMovingVehicles(System.Collections.Generic.List)”匹配的最佳重载方法具有一些无效参数
编译错误(第29行,第59列):参数1:无法从“System.Collections.Generic.List”转换为“System.Collections.Generic.List”
我应该如何将派生类传递给使用父类使其正确工作的方法

namespace Rextester
{
 abstract class Vehicle{
    public int Speed; 
    }

     class Car: Vehicle{
     public String VIN;   
    }

     class Plane : Vehicle{
     public int altitude;   
    }

public class Program
{


    public static void Main(string[] args)
    {

        var cars= new List<Car>();
        var planes = new List<Plane>();
        List<Vehicle> movingCars= getMovingVehicles(cars);
        List<Vehicle> movingPlanes=getMovingVehicles(planes);

    }

     static List<Vehicle> getMovingVehicles(List<Vehicle> vehicles){
        List<Vehicle> movingVehicles=new List<Vehicle>();
        foreach( Vehicle v in vehicles){
        if(v.Speed>0)
             movingVehicles.Add(v);

        }

        return movingVehicles;
    }

}
}
名称空间测试仪
{
抽象类车辆{
公共交通速度;
}
汽车类别:汽车{
公共字符串VIN;
}
飞机类别:汽车{
公共高度;
}
公共课程
{
公共静态void Main(字符串[]args)
{
var cars=新列表();
var planes=新列表();
列出移动车辆=获取移动车辆(车辆);
列表移动平面=获取移动车辆(平面);
}
静态列表getMovingVehicles(列表车辆){
列表移动车辆=新列表();
foreach(车辆中的车辆v){
如果(v.速度>0)
移动车辆。添加(v);
}
返回移动车辆;
}
}
}

只需将函数更改为。类型为variant,而为co variant,它接受派生类型的集合:

static List<Vehicle> getMovingVehicles(IReadOnlyList<Vehicle> vehicles){

有关协方差的更多信息:

问题不在于传递的是派生类而不是基类;这是允许的。问题是您正在传递派生类项的可变集合,这是不允许的

幸运的是,您并没有将车辆列表视为一个完整的列表:您只使用了它的一个方面,即它的枚举能力。因此,您可以将
List
替换为
IEnumerable
,这更“宽容”。特别是,只要
Car
继承自
Vehicle
,它就允许您在其位置传递
IEnumerable

static List<Vehicle> GetMovingVehicles(IEnumerable<Vehicle> vehicles) {
    return vehicles.Where(v => v.Speed != 0).ToList();
}
静态列表GetMovingVehicles(IEnumerable vehicles){
返回车辆。其中(v=>v.速度!=0)。ToList();
}

请注意,使用LINQ可以在不使用循环的情况下生成所需的结果。

您可以使用LINQ转换或强制转换列表。看看:

你可以做:

List<BaseClass> listOfBaseClass= new List<DerivedClass>().ConvertAll(x => (BaseClass)x);
List listOfBaseClass=new List().ConvertAll(x=>(基类)x);
或:

List listOfBaseClass=new List().Cast().ToList();
另一个选项是使用通用
静态列表getMovingVehicles(列出车辆),其中T:车辆{
列表移动车辆=新列表();
foreach(车辆中的车辆v){
如果(v.速度>0)
移动车辆。添加(v);
}
返回移动车辆;
}

汽车
飞机
应该是
列表
。了解协方差。您可以使用
IReadOnlyList
。了解C#命名约定。公共名称应为大写。相关:这可能是一个单独的问题,但您如何确定
IReadOnlyList
是共同变体?你怎么知道
列表
不是呢?@Rainbolt
接口IReadOnlyList
中的“
out
”表示协变。使用
接口列表
可以看到没有
输出
。(如果在中有一个“
”,它将是相反的。)接口定义中的类型参数具有
out
关键字(
IReadOnlyList
),该关键字指定类型是协变的。
List<BaseClass> listOfBaseClass= new List<DerivedClass>().ConvertAll(x => (BaseClass)x);
List<BaseClass> listOfBaseClass = new List<DerivedClass>().Cast<BaseClass>().ToList();
Another option is to use a generic

      static List<Vehicle> getMovingVehicles<T>(List<T> vehicles) where T:Vehicle {
            List<Vehicle> movingVehicles=new List<Vehicle>();
            foreach( Vehicle v in vehicles){
            if(v.Speed>0)
                 movingVehicles.Add(v);

            }

        return movingVehicles;
    }