将派生 class 传递给使用父 class 的方法 c#
Pass derived class to method which use parent class c#
今天我参加了测试,任务是将静态方法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>'
我应该如何将派生 class 传递给使用父 class 的方法才能使其正常工作?
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;
}
}
}
只需将您的函数更改为采用 IReadOnlyList<Vehicle>
. The List<Vehicle>
type is in-variant whereas IReadOnlyList<Vehicle>
是协变体,它接受派生类型的集合:
static List<Vehicle> getMovingVehicles(IReadOnlyList<Vehicle> vehicles){
如果这不可能,那么您可以在将列表传递给方法时将其转换为适当的类型:
getMovingVehicles(cars.ConvertAll(x => (Vehicle) x));
有关协方差的更多信息:https://docs.microsoft.com/en-us/dotnet/standard/generics/covariance-and-contravariance
问题不在于您传递的是派生 class 而不是基础 class;那将是允许的。问题是您正在传递派生项的可变集合 class,这是不允许的。
幸运的是,您没有将车辆列表视为完整列表:您只使用了它的一个方面 - 即它的枚举能力。因此,您可以将 List<Vehicle>
替换为 IEnumerable<Vehicle>
,"forgiving" 多得多。特别是,只要 Car
继承自 Vehicle
:
,它就可以让您在其位置传递 IEnumerable<Car>
static List<Vehicle> GetMovingVehicles(IEnumerable<Vehicle> vehicles) {
return vehicles.Where(v => v.Speed != 0).ToList();
}
请注意使用 LINQ 生成您需要的结果而不使用循环。
您可以转换列表或使用 linq 转换它。看看:this
你可以这样做:
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;
}
今天我参加了测试,任务是将静态方法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>'
我应该如何将派生 class 传递给使用父 class 的方法才能使其正常工作?
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;
}
}
}
只需将您的函数更改为采用 IReadOnlyList<Vehicle>
. The List<Vehicle>
type is in-variant whereas IReadOnlyList<Vehicle>
是协变体,它接受派生类型的集合:
static List<Vehicle> getMovingVehicles(IReadOnlyList<Vehicle> vehicles){
如果这不可能,那么您可以在将列表传递给方法时将其转换为适当的类型:
getMovingVehicles(cars.ConvertAll(x => (Vehicle) x));
有关协方差的更多信息:https://docs.microsoft.com/en-us/dotnet/standard/generics/covariance-and-contravariance
问题不在于您传递的是派生 class 而不是基础 class;那将是允许的。问题是您正在传递派生项的可变集合 class,这是不允许的。
幸运的是,您没有将车辆列表视为完整列表:您只使用了它的一个方面 - 即它的枚举能力。因此,您可以将 List<Vehicle>
替换为 IEnumerable<Vehicle>
,"forgiving" 多得多。特别是,只要 Car
继承自 Vehicle
:
IEnumerable<Car>
static List<Vehicle> GetMovingVehicles(IEnumerable<Vehicle> vehicles) {
return vehicles.Where(v => v.Speed != 0).ToList();
}
请注意使用 LINQ 生成您需要的结果而不使用循环。
您可以转换列表或使用 linq 转换它。看看:this
你可以这样做:
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;
}