首页 > 解决方案 > C#:如何将对象添加到数组中?

问题描述

我是 C# OOP 的新手,将对象放入数组中比 JS 稍微困难一些。这是我的第一个练习,对于如何将对象放入数组中的任何帮助表示赞赏。

我希望输出是cars = { porsche, mercedes, bmw, punto, ferrari};

我做错了什么?

static void Main(string[] args)
{
    // Create 5 Car Objects and add them to Array
    var porsche = new Car("Porshe", 340);
    var mercedes = new Car("Mercedes", 320);
    var bmw = new Car("BMW", 330);
    var punto = new Car("Punto", 220);
    var ferrari = new Car("Ferrari", 380);

    // Cars to array
    object[] cars = new object[5];
    cars[0] = porsche;
    cars[1] = mercedes;
    cars[2] = bmw;
    cars[3] = punto;
    cars[4] = ferrari;
    
    foreach(var car in cars)
    {
        Console.WriteLine($"some {car}");
    }
}

class Car
{
    public Car(string model, int speed)
    {
        Model = model;
        Speed = speed;
    }

    public string Model { get; set; }
    public int Speed { get; set; }

    public int CalculateSpeed( int speed, int skill)
    {
        return speed * skill;
    }
}

控制台输出:

some OOP_Car_Human.Car
some OOP_Car_Human.Car
some OOP_Car_Human.Car
some OOP_Car_Human.Car
some OOP_Car_Human.Car

标签: c#

解决方案


正如我在评论中提到的,C# 是强类型的。而不是创建一个对象数组(可以添加任何类型的任何对象),而是创建一个汽车数组:

 Car[] cars = new Car[5];

现在,您的数组只能包含Car对象(或Car子类的实例)。没有人可以说cars[2] = new Horse("Secretariat");(可以用object[]数组完成的事情。

您也可以var改用:

 var cars = new Car[5];

这样,您不必键入两次类型规范。这两个语句的含义完全相同。仅var当编译器可以从上下文中推断出赋值右侧的类型时,才能使用。该类型应用于左侧的变量。

您还可以在创建数组时对其进行初始化:

var cars = new Car[] {
     porsche,
     mercedes,
     bmw,
     punto,
     ferrari,
};

当您这样做时,您不必在数组构造函数表达式中包含数组大小(您可以,但您不必这样做)。

你也可以这样做:

var cars = new Car[] {
    new Car("Porshe", 340),
    new Car("Mercedes", 320),
    new Car("BMW", 330),
    new Car("Punto", 220),
    new Car("Ferrari", 380),
};

除了用于数组初始化之外,您不会使用 names porshemercedes等,因此您实际上并不需要它们。您可以使用它们(并且在运行时可能不会再花费,但是...)

正如@crowcoder 所指出的,您确实应该添加一个ToString方法:

public override string ToString()
{
    return Model;
}

这将使您的代码按照您期望的方式运行。该Console.WriteLine方法在传递时string将输出一个字符串。但是,如果它传递了任何其他类型的对象,它将调用ToString该对象。该类object声明ToString为一个virtual可覆盖的方法。该类object包括 的实现ToString,但它唯一知道的对象是对象的类型,因此它用作返回的字符串。由于该方法是虚拟的/可覆盖的,(即几乎每种类型)的子类object都可以覆盖该方法并做任何他们想做的事情。你的期望是汽车的Model属性会被输出,所以这就是它的作用。

其他人正在将您从数组推向列表。这样做有充分的理由。其中之一(Javascript 程序员熟悉)是 List 是有弹性的;它会随着你添加东西而增长(就像 Javascript 数组一样)。C# 数组必须是固定大小的。

另一个注意事项。正如您所发现的,当您有一个包含 的对象数组时Cars,C# 的类型安全性将阻止您直接在编译器仅知道作为对象的对象上调用特定于 Car 的方法。在 C# 中,变量类型 asobject可以引用任何东西,但它只有极少数ToString可以直接调用的方法(如 )(与 Javascript 不同,其中成员绑定是在运行时而不是编译时完成的)。

如果你想获得类似 Javascript 的变量行为,你可以使用dynamic类型 ( var cars = new dynamic[]{bmw, etc.})。类型化的变量dynamic可以表现得非常像 Javascript 变量(并且有些类型的行为几乎完全像 Javascript 对象(它们派生自Expando))。

如果你有一个像(就像你展示的那样): 的表达式Console.WriteLine($"some {car.Model}");,并且car是 typed dynamic,那么,在运行时,car检查类型以确定它是否有一个Model属性。如果是,则对其进行评估。如果没有,它会抛出异常。所有这些都是在运行时完成的。您看到的错误(CS1061:'object' 不包含'Model' 的定义)发生在编译时。由于类型安全,Car已知 a 具有Model属性并且不需要进行运行时检查。

也就是说,几乎每个监视 C# 标签的人都会告诉不要使用dynamic. C# 的类型安全是它的一大优势(一旦你习惯了它,它就会变得有意义)。


推荐阅读