2

I want to manipulate an instance by a delegate, which is a property of the class itself. The parameter of the delegate should always be the instance itself (even in derived classes!).

See code below. I know that the code is not compiling because I have to cast car1 to type car, I'm looking for a solution without casting.

Code

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; }
}

EDIT: Changed Code!

My question is, is there a good solution to handle all this just in the base class, but in the action I want to use the derived classes without casting.

Snowcrack
  • 549
  • 1
  • 5
  • 13
  • Where is a problem? You can use [virtual](http://stackoverflow.com/q/8309419/1997232) method which all inherited class override if that is the problem. – Sinatr Aug 19 '16 at 10:08
  • Car.VehicleManipulator action is null, you never assigned it, make it virtual and compiler will look for implementation in derived classes – A.T. Aug 19 '16 at 10:21
  • @A.T. on the contrary *that* property is assigned but the method uses the *base class's* property. This isn't about nulls, it's about inheritance – Panagiotis Kanavos Aug 19 '16 at 10:23
  • 1
    @Snowcrack - By just removeing the property in the derived you are not doing the casting. That's the idea of inheritance in the first place - you add more over that base class. Why will you want another property of the same type and name in the derived? – Gilad Green Aug 19 '16 at 10:23
  • 1
    You have reintroduced the `VehicleManipulator` in the derived class, was that intentional? Do you know the effect of this? – Lasse V. Karlsen Aug 19 '16 at 10:23
  • @PanagiotisKanavos updated my comment – A.T. Aug 19 '16 at 10:24

2 Answers2

4

You are close. The reason you get a NullReferenceException for this line car.ManipulateVehicle(); is because the VehicleManipulator action is null.

enter image description here

And as you see the VehicleManipulator property of the base class is null.

Now how can it be null if just above the line you fail at you are assigning the actions? So the problem is that in your derived class, car, you have a new different property with the name VehicleManipulator which hides the base one. So when you assign car.VehicleManipulator you are actually assigning the property in the derived class and not in the base class.

Remove that from the derived class at it will work.

If, for a reason that I can't yet understand, you do want to keep the property in the derived class then when doing the assigning you can specify that you want to assign to the base class like this:

enter image description here

Gilad Green
  • 36,708
  • 7
  • 61
  • 95
3

If you want to avoid casting, make Vehicle generic like:

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

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

It looks a little weird but it means if you have an instance of car the manipulator works on cars and if you have a truck it works on trucks and so on. Vehicle should probably be abstract.

Mike Sackton
  • 1,094
  • 7
  • 19