2

I have tried to add two classes (car and van) in an arraylist but seems like the list is defined by the first class (car) and when trying to add the other class (van) I get the runtime error

System.InvalidCastException: 'Unable to cast object of type 'CarBroker.Car' to type 'CarBroker.Van'.

I believe the error is caused by the arraylist is defined when creating the first entry of the type 'Car' and when trying to add a different type 'Van' the error occurs.

Is there another list that can be used instead?

public class List // Global ArrayList to store car data
{ public static ArrayList vehicle = new ArrayList(); }
static void Main(string[] args)
{
    Car car = new Car();
    car.SetVehicleData();
    car.SetOwnerData();

    List.vehicle.Add(car);

    Van van = new Van();
    van.SetVehicleData();
    van.SetCompanyData();

    List.vehicle.Add(van);

    Admin a1 = new Admin();
    a1.ListAll();

    Console.ReadKey();

}

When running my ListAll() method the ideal output would be first list entry with the class 'car' and the second entry with the class 'van'

Instead I get the error mentioned above.

Anyone that can help me on the way using the right list or another function? I am attending a basic C# class so I am not that advanced :)

doppelgreener
  • 4,809
  • 10
  • 46
  • 63
  • 2
    do `Car` and `Van` share an interface/base class other than `Object`? if so use `List` – Daniel A. White Apr 24 '19 at 14:32
  • 1
    Create a base class Vehicle and have Van and Car inherit the Vehicle class. – jdweng Apr 24 '19 at 14:32
  • You have various options. Either you make the two classes inherit from a common base type and make the list contain that base type, or you could make one of the types, such as car, the base type for the other. You can also make both types implement a common interface and make the list out of that interface, or you can make the list hold just `object` elements, which can hold anything. – Lasse V. Karlsen Apr 24 '19 at 14:33
  • 1
    As an aside, read [What's Wrong with an ArrayList?](https://stackoverflow.com/q/3326599/1364007). – Wai Ha Lee Apr 24 '19 at 14:45
  • No, the list will preserve your new properties, but when you iterate through the list you have to test the objects. For example: foreach (Vehicle vehicle in List) { if (vehicle is Car) { Car car = vehicle as Car car.customProp } if (vehicle is Van) { Van van = vehicle as Van van.VanCustomProp } } – Alex M Apr 24 '19 at 17:25
  • Thanks all for the help. It works with your help using a generic List. Now I just need to snatch the different types `CarBroker.Car` and ´CarBroker.Van` from the list to use it for an unique ID generator. – Jesper Levi Hemmingsen Apr 24 '19 at 18:13

2 Answers2

3

Don't use ArrayList, use generic List<T> and you will be able to do that as long as both classes inherit from the same base class. Polymorphism.

Create a new List<BaseClass>. We assume that Car and Van inherit from the BaseClass. Then

List.Add(Car)
List.Add(Van)

When you iterate through the list you have to test the objects. For example:

  foreach (Vehicle vehicle in List) 
  { 
        if (vehicle is Car car) 
        { 
            car.customProp 
        } 
        if (vehicle is Van van) 
        { 
           van.VanCustomProp 
        } 
   } 
Tim Rogers
  • 21,297
  • 6
  • 52
  • 68
Alex M
  • 141
  • 2
  • 6
  • Hi Sinatr, the classes `Van` and `Car` inherit variables from a superclass or upperclass called `Vehicle` but I have added new variables in `Van` and `Car`. Will List ignore the differences in the object added to the list? – Jesper Levi Hemmingsen Apr 24 '19 at 17:21
  • @JesperLeviHemmingsen No, the list will preserve your new properties, but when you iterate through the list you have to test the objects. For example: foreach (Vehicle vehicle in List) { if (vehicle is Car) { Car car = vehicle as Car car.customProp } if (vehicle is Van) { Van van = vehicle as Van van.VanCustomProp } } – Alex M Apr 24 '19 at 17:30
  • posting code here is exhausting – Alex M Apr 24 '19 at 17:32
  • 1
    select code, press Ctrl+K. – Heretic Monkey Apr 24 '19 at 17:39
  • If you need to check whether a vehicle is a car or a van from the list then you probably have code smell – Smithy Apr 25 '19 at 10:26
1

To be able to do what you're trying to do you'll need a common interface between Car and Van; You can do this 2 ways via a base class or an interface:

public class Vehicle {
    public string Name { get; set; }
}

public interface IVehicle {
    void SetVehicleData(string data);
    void SetOwnerData(string data);
}

Then your car and van will inherit those interfaces:

public class Car : Vehicle, IVehicle {
    public void SetOwnerData(string data) {
        throw new NotImplementedException();
    }

    public void SetVehicleData(string data) {
        throw new NotImplementedException();
    }
}
public class Van : Vehicle, IVehicle {
    public void SetOwnerData(string data) {
        throw new NotImplementedException();
    }

    public void SetVehicleData(string data) {
        throw new NotImplementedException();
    }
}

Then you can use it like so:

        var vehicles = new List<Vehicle>();

        var car = new Car() { Name = "Rover" };
        car.SetOwnerData("data");
        car.SetVehicleData("Rover 75");

        vehicles.Add(car);

        var van = new Van() { Name = "Transit" };
        van.SetOwnerData("data");
        van.SetVehicleData("Transit Van");

        vehicles.Add(van);

If your SetOwner and SetVehicle behave in the same way then put this behaviour in your base class:

public class Vehicle : IVehicle {
    public string Name { get; set; }
    public string OwnerData { get; set; }
    public string VehicleData { get; set; }
    public void SetOwnerData(string data) {
        OwnerData = data;
    }

    public void SetVehicleData(string data) {
        VehicleData = data;
    }
}
Smithy
  • 2,170
  • 6
  • 29
  • 61
  • Thanks, I will try out the solutions. I have a base class named `Vehicle` already, so perhaps I just need to modify my code a bit to get it to work! – Jesper Levi Hemmingsen Apr 24 '19 at 17:24
  • In that case you just need to change line: `public static ArrayList vehicle = new ArrayList(); ` to be `public static List vehicle = new List();` – Smithy Apr 24 '19 at 17:46