简体   繁体   English

如何从列表访问属性

[英]how to access property from list

If I have the following code and want to iterate the list of vehicles and display the Price, how can I access that property? 如果我有以下代码,并且想要遍历车辆列表并显示价格,该如何访问该属性?

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

    public class ElectricalDriven : Vehicle
    {
        public string SuperChargerCord { get; set; }
    }

    public class GasolinDriven : Vehicle
    {
        public string GasolineTank { get; set; }
    }

        var myListOfVechicles = new List<Vehicle>();
        myListOfVechicles.Add(new ElectricalDriven { Name = "Tesla", Price = "100 000", SuperChargerCord = "Yellow cord"});
        myListOfVechicles.Add(new GasolinDriven { Name = "Ford", Price = "50 000", GasolineTank = "Large VZ Tank"});


        foreach (var row in myListOfVechicles)
        {
            Console.WriteLine($"- {row.Name}");
        }

The problem is that Vehicle does not have a Value property, so you can't ask for it in a type-safe manner. 问题是, Vehicle具有 Value属性,所以你不能在一个类型安全的方式提出要求。

Some options are: 一些选项是:

  • Override ToString so that the class determines what is displayed: 覆盖ToString以便该类确定显示的内容:
  • Add a virtual method to VEhivel like GetDescription that returns a string if you don't want that string to override ToString` VEhivel like添加一个VEhivel like GetDescription的virtual方法, that returns a string if you don't want that string to override ToString that returns a string if you don't want that string to override方法将that returns a string if you don't want that string to override
  • Move Price to Vehicle or a subtype that ElectricalDriven and GasolinDriven both inherit from. Price移动到VehicleGasolinDriven继承ElectricalDrivenGasolinDriven的子类型。

In the foreach you can check if the current 'row' is ElectricalDriven or GasolinDriven with the 'is' operator and then cast the row to the matched concrete implementation. 在foreach中,您可以使用“ is”运算符检查当前的“行”是ElectricalDriven还是GasolinDriven,然后将该行转换为匹配的具体实现。 Should be something like that: 应该是这样的:

if (row is ElectricalDriven)
{
    Console.WriteLine($"Price: {((ElectricalDriven)row).Price}");
}
else if (row is GasolinDriven)
{
    Console.WriteLine($"Price: {((GasolinDriven)row).Price}");
}

However, you can see that the more different vehicles, the more ifs. 但是,您可以看到,不同的车辆越多,ifs越多。 You should probably move the price property in the base class or in an interface. 您可能应该在基类或接口中移动price属性。

EDIT: Seeing that the author moved the price property to the Vehicle class, you can now access it just like you accessed the Name property. 编辑:看到作者将price属性移到Vehicle类,现在就可以像访问Name属性一样访问它。

If you want to define a unique property for both Electric and Gasoline vehicles, and be able to retrieve its value from the generic vehicle class, you can declare a virtual method and override it in the inheriting classes: 如果要为电动和汽油车辆定义一个唯一的属性,并且能够从通用车辆类中检索其值,则可以声明一个虚拟方法并在继承的类中重写它:

 public class Vehicle
{
    public string Name { get; set; }
    public virtual string GetCustomProperty() { return string.Empty; }
}

public class ElectricalDriven : Vehicle
{
    public string ElectricalVehicleProperty { get; set; }
    public override string GetCustomProperty() { return ElectricalVehicleProperty; }
}

public class GasolinDriven : Vehicle
{
    public string GasolinVehicleProprety { get; set; }
    public override string GetCustomProperty() { return GasolinVehicleProprety; }
}
class Program
{
    static void Main(string[] args)
    {
        var myListOfVechicles = new List<Vehicle>();
        myListOfVechicles.Add(new ElectricalDriven { Name = "Tesla", ElectricalVehicleProperty = "100 000" });
        myListOfVechicles.Add(new GasolinDriven { Name = "Ford", GasolinVehicleProprety = "50 000" });

        foreach (var row in myListOfVechicles)
        {
            Console.WriteLine("Price: " + row.GetCustomProperty()); //will output 100,000 and 50,000
        }
        Console.Read();
    }
}

By doing this: 通过做这个:

var myListOfVechicles = new List<Vehicle>();
myListOfVechicles.Add(new ElectricalDriven { Name = "Tesla", Price = "100 000" });
myListOfVechicles.Add(new GasolinDriven { Name = "Ford", Price = "50 000" });

The compiler will assign an object of the subclass (like ElectricalDriven) to object to the base class (Vehicle) after implicitly converting it to the base class type. 隐式将子类的对象转换为基类类型 ,编译器将为其分配对象的子类(如ElectricalDriven)的对象。

Know because of this conversion, when you are trying to access that object you're accessing an object that only have the base class members which is only Name . 知道由于这种转换,当您尝试访问该对象时,您正在访问的对象只有基类成员,而该成员只有Name

To be able to access Price you need to explicitly cast the object to the subclass type before accessing its members. 为了能够访问Price您需要在访问其成员之前将对象显式转换为子类类型。 The simplest for example you can try this: 例如,最简单的方法是:

   string name, price;
    foreach (var item in myListOfVechicles)
    {
        name = item is ElectricalDriven ? 
                       (item as ElectricalDriven).Name : 
                       (item as GasolinDriven).Name;
        price = item is ElectricalDriven ? 
                        (item as ElectricalDriven).Price :
                        (item as GasolinDriven).Price;

        Console.WriteLine($"Name: {name} - Price: {price}");
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM