【问题标题】:Is it possible to create a list where two different classes can be added? [duplicate]是否可以创建一个可以添加两个不同类的列表? [复制]
【发布时间】:2019-09-13 21:33:48
【问题描述】:

我尝试在数组列表中添加两个类(汽车和货车),但似乎列表是由第一个类(汽车)定义的,当尝试添加另一个类(货车)时,我得到 运行时错误

System.InvalidCastException: '无法转换类型的对象 'CarBroker.Car' 输入 'CarBroker.Van'。

我认为该错误是由在创建“Car”类型的第一个条目时定义的 arraylist 引起的,并且在尝试添加不同类型的“Van”时会发生错误。

还有其他可以代替的列表吗?

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();

}

当运行我的 ListAll() 方法时,理想的输出将是第一个列表条目与类 'car' 和第二个条目与类 'van'

相反,我得到了上面提到的错误。

谁能帮助我使用正确的列表或其他功能?我正在上一个基本的 C# 课程,所以我不是那么先进 :)

【问题讨论】:

  • CarVan 是否共享除 Object 之外的接口/基类?如果是这样,请使用List<YourBase>
  • 创建一个基类 Vehicle 并让 Van 和 Car 继承 Vehicle 类。
  • 您有多种选择。要么让这两个类从一个公共基类型继承并让列表包含该基类型,要么你可以将其中一种类型(例如 car)作为另一种的基类型。您还可以让这两种类型都实现一个通用接口,并让列表脱离该接口,或者您可以让列表只包含 object 元素,它可以包含任何东西。
  • 顺便说一句,请阅读What's Wrong with an ArrayList?
  • 不,列表将保留您的新属性,但是当您遍历列表时,您必须测试对象。例如: foreach (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 } }

标签: c#


【解决方案1】:

不要使用ArrayList,使用泛型List<T>,只要两个类都继承自同一个基类,您就可以这样做。 多态性。

创建一个新的List<BaseClass>。我们假设CarVan 继承自BaseClass。那么

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

当您遍历列表时,您必须测试对象。例如:

  foreach (Vehicle vehicle in List) 
  { 
        if (vehicle is Car car) 
        { 
            car.customProp 
        } 
        if (vehicle is Van van) 
        { 
           van.VanCustomProp 
        } 
   } 

【讨论】:

  • 嗨 Sinatr,VanCar 类从名为 Vehicle 的超类或上级类继承变量,但我在 VanCar 中添加了新变量。 List 会忽略添加到列表中的对象的差异吗?
  • @JesperLeviHemmingsen 不,列表将保留您的新属性,但是当您遍历列表时,您必须测试对象。例如: foreach (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 } }
  • 这里发代码好累
  • 选择代码,按Ctrl+K。
  • 如果您需要检查列表中的车辆是汽车还是货车,那么您可能有代码气味
【解决方案2】:

为了能够做您想做的事情,您需要在 Car 和 Van 之间建立一个通用接口;您可以通过基类或接口两种方式:

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

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

那么您的汽车和面包车将继承这些接口:

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

那么你可以这样使用它:

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

如果您的 SetOwnerSetVehicle 的行为方式相同,则将此行为放在您的基类中:

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

【讨论】:

  • 谢谢,我会尝试解决方案。我已经有一个名为Vehicle 的基类,所以也许我只需要稍微修改我的代码就可以让它工作!
  • 在这种情况下,您只需将行:public static ArrayList vehicle = new ArrayList(); 更改为 public static List&lt;Vehicle&gt; vehicle = new List&lt;Vehicle&gt;();
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-04-03
  • 2011-06-15
  • 2011-04-15
  • 1970-01-01
  • 1970-01-01
  • 2015-02-12
  • 1970-01-01
相关资源
最近更新 更多