C# 将各种 class 对象动态传递给单个方法

C# Pass various class objects to a single method dynamically

假设我有两个 classes 并且我想创建一个方法来处理来自两个 classes 的数据,我如何设置一个可以接受两者的方法将它们创建为它们类型的对象?

Public classs Car:Wheel
{

  public Color color {get; set;}
}

Public class Bike:Wheel

{
public bool hasRadio {get ; set;} 
public Color color {get; set;} 
}

Public class Wheel
{
  public WheelRimType {get; set;}
  public int WheelSize {get; set;} 
}

我想将汽车或自行车的 class 动态传递给一个方法。在那个方法中,如何将它转换为正确的对象,这样我就不必为每个对象编写两次相同的方法?

Car c = new Car();
Bike b = new Bike();

ValidateVehichle(c);

private void ValidateVehicle(Type T??)
{
//convert to either car or bike here
} 

使用泛型:

ValidateVehichle<Car>(car);

private void ValidateVehicle<T>(T vehicle)
{
    // no convertion needed. use T as the type of the object
    T vehicle2 = vehicle;
    .....
} 

关于泛型的更多信息:https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/types/generics

您可以使用泛型并执行如下操作:

void Main()
{
    Car car = new Car();
    car.color = Color.Black;
    car.WheelSize = 22;
    
    ValidateVehicle<Car>(car)
}

private void ValidateVehicle<T>(T vehicle)
{
    // You still need to determine what time this object is
    T someVehicle = vehicle;
    Console.WriteLine("This is a generic method");
}

您也可以使用重载方法。您可以像这样拥有一个具有无限重载的方法名称:

void Main()
{
    Car car = new Car();
    car.color = Color.Black;
    car.WheelSize = 22;
    
    Bike bike = new Bike();
    bike.color = Color.Red;
    bike.hasRadio = false;
    bike.WheelSize = 12;
    
    ValidateVehicle(car);
    ValidateVehicle(bike);
    
}

// You can define other methods, fields, classes and namespaces here
public class Car: Wheel
{
  public Color color { get; set; }
}

public class Bike : Wheel
{
    public bool hasRadio { get; set; }
    public Color color { get; set; }
}

public class Wheel
{
    public int WheelSize { get; set; } 
}

private void ValidateVehicle(Car car)
{
    Console.WriteLine("This is your car method");
}

private void ValidateVehicle(Bike bike)
{
    Console.WriteLine("This is your bike method");
}

输出为:

This is your car method
This is your bike method
  1. 你的汽车和自行车“有”轮子,但不是“轮子”,所以在考虑继承时你可能想阅读更多关于 has-a-is-a 术语的信息:has-a-is-a-terminology-in-object-oriented-language

  2. 我相信你最好为 Car 和 Bike 创建一个基础 class 并在这个基础中放置一个验证方法 class 然后可以在 Car 中实现和自行车。类似于以下内容:

  3. 基础 class VehicleBase 将包含公共属性,colorWheels 属性遵循“has-a”逻辑,在示例中,VehicleBase 将包含一个 IEnumerable<T>,其中 TWheel,其中车辆可以有零个或多个车轮。


public abstract class VehicleBase
{
   public abstract bool Validate();
   public Color color { get; set;}
   public IEnumerable<Wheel> Wheels {get; set;}
}

public class Car : VehicleBase
{
   public override bool Validate()
   {
      //do Car validation
   }
}

public class Bike : VehicleBase
{
    public bool hasRadio {get ; set;} 
    public override bool Validate()
    {
      //do Bike validation
    }
}

public class Wheel
{
    public WheelRimType { get; set;}
    public int WheelSize {get; set;} 
}

两个经典的可能性

class Vehicle{

}

class Car : Vehicle{
}

class Bike : Vehicle{

}

那你就可以了

private void ValidateVehicle(Vehicle v)
{
//convert to either car or bike here
} 

进行验证的惯用方法实际上具有以下内容

abstract class Vehicle{
      virtual bool Validate();
}

class Car : Vehicle{
     override bool Validate(){
     }
}

class Bike : Vehicle{
     override bool Validate(){
     }

}

你只需要做 vobj.Validate()

其中 vobj 是车辆的实例

也可以使用接口

interface IVehicle{

}

class Car : IVehicle{
}

class Bike : IVehicle{

}

private void ValidateVehicle(Vehicle v)
{
//convert to either car or bike here
} 

典型的解决方案是引入一个通用接口,以便 ValidateVehicle 可以使用任一类型:

public interface IVehicle{
    Color color {get; set;}
}

public class Car:Wheel, IVehicle {
    public Color color {get; set;}
}
public class Bike:Wheel, IVehicle
{
   public bool hasRadio {get ; set;} 
   public Color color {get; set;} 
}

private void ValidateVehicle(IVehicle vehicle)
{
   // Implementation here
}

这显然需要 IVehicle 公开 ValidateVehicle 使用的所有方法和属性。

如果汽车和自行车的验证逻辑不同,您应该将验证方法放在您的车辆类型上。这样每辆车都可以以自己的方式进行验证。

public interface IVehicle{
    Color color {get; set;}
    bool ValidateVehicle();
}

第三种方法是使用类型检查:

private void ValidateVehicle(object vehicle)
{
   if(vehicle is Car car){
      ...
   }
   if(vehicle is Bike bike){
      ...
   }
}

但这并不容易维护。假设你介绍了一辆摩托车,如果你使用一个接口,你只需要让你的新车继承那个接口,如果你犯了任何错误,编译器就会抱怨。如果你使用 type-checks,你需要记住你检查类型的所有不同地方,并为你的摩托车添加另一个检查,这很快就会成为维护的噩梦。由于这种类型检查通常不受欢迎。

我猜这是为了作业,但我不喜欢这样的面向对象示例。值得注意的是,汽车 不是 轮子,它 轮子,即轮子应该是 属性 而不是 继承.

在演示面向对象时,我通常更喜欢几何,它有很多组合和继承的例子,在实际程序中确实很有用。相比之下,我很难想象车辆继承层次结构实际上在哪里有用。