使用派生类类型作为基类的通用操作的参数

时间:2016-08-19 10:05:54

标签: c# generics inheritance action

我想通过委托来操作实例,委托是类本身的属性。委托的参数应该始终是实例本身(即使在派生类中!)。

见下面的代码。我知道代码没有编译,因为我必须将car1转换为car car,我正在寻找一种没有强制转换的解决方案。

代码

static void Main(string[] args)
{
    var car = new Car();
     car.VehicleManipulator = car1 => car1.SomeInt++;
     car.ManipulateVehicle();

    Console.WriteLine("end");
    Console.ReadLine();
}

internal class Vehicle
{
    public Action<Vehicle> VehicleManipulator { get; set; }

    public void ManipulateVehicle()
    {
        this.VehicleManipulator(this);
    }
}

internal class Car : Vehicle
{
    public int SomeInt { get; set; }
}

编辑: 改变了代码!

我的问题是,是否有一个很好的解决方案来处理基类中的所有这些,但在操作中我想使用派生类而不进行转换。

3 个答案:

答案 0 :(得分:4)

你很亲密。您为此行NullReferenceException获得car.ManipulateVehicle();的原因是因为VehicleManipulator操作为空。

enter image description here

正如您所看到的,基类的VehicleManipulator属性为null。

现在如果你在失败的线上方分配动作,它怎么能为空呢?所以问题在于,在你的派生类car中,你有一个新的不同的属性,其名称为VehicleManipulator,隐藏了基本属性。因此,当您分配car.VehicleManipulator时,实际上是在派生类中而不是在基类中分配属性。

派生类中删除它会起作用。

如果由于某个我无法理解的原因,您确实希望将该属性保留在派生类中,那么在进行分配时,您可以指定要分配给基类,如下所示:

enter image description here

答案 1 :(得分:2)

如果您想避免施放,请将“车辆”设为通用,如:

class Vehicle<T> where T : Vehicle {
     Action<T> ManipulateVehicle { get; set; }
}

class Car : Vehicle<Car> {
    int SomeInt { get; set; }
}

它看起来有点奇怪,但这意味着如果你有一个汽车的实例,机械手在汽车上工作,如果你有一辆卡车,它可以在卡车上工作等等。车辆应该是抽象的。

答案 2 :(得分:0)

只需从Car class中删除这行代码:

public Action<Car> VehicleManipulator { get; set; }

ManipulateVehicle是基类的方法,在调用时,它使用base(非派生)类的VehicleManipulator属性。

VehicleManipulator属性添加到派生类隐藏基本属性以及何时分配 - base属性的默认值为null,因此NullReferenceException

我还建议将关键字abstract添加到Vehicle的签名,因为它是纯粹的抽象。一个人不能只创造没有类型的车辆,只有汽车,卡车,摩托车等

因此,工作代码可以是这样的:

abstract internal class Vehicle
{
    public virtual Action<Vehicle> VehicleManipulator { get; set; }

    public void ManipulateVehicle()
    {
        this.VehicleManipulator(this);
    }
}

internal class Car : Vehicle
{
}