3

The real problem comes up with Reflection and assembly patching/hooking. I'll put a simple example to show up my question without being too hard to understand the main problem.

So let's imagine I have these basic classes :

public class Vehicle
{
    public string Name;
    public string Price;

    public void DoSomething()
    {
        Main.Test(this);
    }
}

public class Car : Vehicle
{
    public int Wheels;
    public int Doors;
}

And on the main code I run this up :

public class Main
{
    public void Start()
    {
        Car testCar = new Car()
        {
            Name = "Test Car",
            Price = "4000",
            Wheels = 4,
            Doors = 4
        };

        testCar.DoSomething();
    }

    public static void Test(Vehicle test)
    {
        // Is this allowed ?
        Car helloWorld = (Car) test;
    }   
}

Okay, the question is :

Is that cast allowed (in the static method Test) ? Will I lose the Car properties but keep the Vehicle ones ?

In case it's wrong, is there any other way to do it ?

Thanks.

Snak
  • 673
  • 1
  • 5
  • 19
  • "In case it's wrong, is there any other way to do it ?" To do what? – Ivan Stoev Dec 19 '15 at 20:07
  • see downcasting: http://stackoverflow.com/questions/1524197/downcast-and-upcast – flo scheiwiller Dec 19 '15 at 20:10
  • 2
    Welcome to Stack Overflow. That should be something which is relatively easy to test. So have you tried it? If not, that's kind of a prerequisite to asking a question. If you have, is there a specific problem you're having? – ardila Dec 19 '15 at 20:10
  • @IvanStoev To get the object as a Car and not as a Vehicle. – Snak Dec 19 '15 at 20:11
  • What if it's a `Truck`? I mean, imagine you have another class `Truck : Vehicle`, how do you know that `Vehicle test` is `Car` and not `Truck` or any other `Vehicle` derived class – Ivan Stoev Dec 19 '15 at 20:15
  • I understand that but the real problem i'm facing happens to be this : I have a LightAttachment component which has a property that references the BaseWeapon but only RangedWeapons (which derive from BaseWeapon) have the Light component, so I know 100% it must be a RangedWeapon. Therefore, I cast the BaseWeapon to RangedWeapon. The code is from a game made in Unity (not by me), i'm just modding some parts through patching the IL code. – Snak Dec 19 '15 at 20:20

3 Answers3

5

The cast of Vehicle to Car is allowed only when the object passed in happens to be Car. Otherwise you get an exception.

There is a cast that does not cause exceptions when the type is wrong:

Car car = test as Car;

This will never throw, but when Vehicle is not a Car, variable car would be null. You could add an if condition to test that the cast has succeeded:

Car car = test as Car;
if (car != null) {
    ...
}
Bus bus = test as Bus;
if (bus != null) {
    ...
}
Rv rv = test as Rv;
if (rv != null) {
    ...
}

However, C# offers an even better solution: method overloading lets you avoid casting altogether.

public class Main {
    public static void Test(Car test) {
        ... // This method will be called by Main.Test(this) of a Car
    }
    public static void Test(Bus test) {
        ... // This method will be called by Main.Test(this) of a Bus
    }
    public static void Test(Rv test) {
        ... // This method will be called by Main.Test(this) of an Rv
    }
}

This works, because the compiler knows the exact type of this variable when you make the Main.Test(this) call.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
2

Yes, the cast is allowed, and you will not "lose" any properties. But if Vehicle test is not, in fact, an instance of Car then your cast will throw an InvalidCastException.

driis
  • 161,458
  • 45
  • 265
  • 341
0

Yes, it is allowed. It's named downcasting.

Remember it is possible to check through type introspection to determine whether the type of the referenced object is indeed the one being cast to or a derived type of it.

Kina
  • 34
  • 2