【问题标题】:How to get a property value from a nested class?如何从嵌套类中获取属性值?
【发布时间】:2019-10-10 19:05:10
【问题描述】:

您好,我在获取嵌套类属性值时遇到问题。我想要

class Car
{

  string name;
  string model;

  class Engine
  {
    public string engineNumber;

    public Engine(string engineNumber)
    {
      this.engineNumber = engineNumber;
    }

  }

  public Car(string name, string model, string engineNumber)
  {

    this.name = name;
    this.model = model;
    Engine e1 = new engine(engineNumber)
  }

}

在这段代码中,我尝试在 Main 类中编写 Console.Write(c1.e1.engineNumber);。有可能得到engineNumber的值吗?

【问题讨论】:

  • 什么是c1?您的代码示例不完整。此外,您可能应该使用属性而不是字段
  • 为什么Engine 定义了一个私有内部类?此外,您不会对在 Car 构造函数中创建的 Engine 执行任何操作。我建议将Engine 移出Car 并将Engine 属性添加到Car

标签: c# oop inner-classes encapsulation abstraction


【解决方案1】:

您通常不希望像以前那样嵌套类定义。如果你有一辆可以使用不同类型发动机的汽车呢?比如说,4升与2升?还是正常吸气与涡轮增压?您可能想要做的是将Engine 作为参数传递给Car

关于从这些对象获取值的实际问题,您还需要定义如何获取和/或更改值。构造函数完成了最初的工作,但是如果EngineCar 在程序运行期间需要更改或获取值怎么办?你需要访问器。

public class Car
{
    public string name { get; private set; }
    public string model { get; private set; }
    public Engine engine { get; private set; }

    public Car(string name, string model, Engine engine)
    {
        this.name = name;
        this.model = model;
        this.engine = engine;
    }
}

class Engine
{
    public string number { get; private set; }
    // other values as necessary

    public Engine(string number)
    {
        this.number = number;
    }
}

var newCar = new Car('Volvo', 'Hatchback', new Engine('someNumber'));
var engineNumber = newCar.engine.number;

在此示例中,您可以通过引用对象属性 (get) 来获取所需的数据,但您将无法以相同的方式更改该数据 (private set)。相反,您需要创建对象方法(如果您是 OOP 新手,请阅读:函数)来显式更改这些值。

【讨论】:

    【解决方案2】:

    实现它的方法很多,这是我的:),诀窍是区分类声明和类实现。

    using System;
    
    public class Program
    {
      public static void Main()
      {
        var c = new Car("Name", "Model", "Engine");
        Console.WriteLine(c.engine.engineNumber);
      }
    
      class Car
      {
        string name;
        string model;
        public Engine engine;
    
        public Car(string name, string model, string engineNumber)
        {
          this.name = name;
          this.model = model;
          this.engine = new Engine(engineNumber);
        }
      }
    
      class Engine
      {
        public string engineNumber;
        public Engine(string engineNumber)
        {
          this.engineNumber = engineNumber;
        }
      } 
    }
    

    你可以看到它在这里运行:https://dotnetfiddle.net/66lGn6

    【讨论】:

    • 谢谢,这正是我的意思:)
    【解决方案3】:

    是的,你会的。

    但是您提供的代码在创建后就丢失了Engine e1,因为您没有将它存储在Car 类级别。

    Engine 类是私有的,应该是公共的。

    它的构造函数应该是internal protected,只允许Car创建它的Engineinternal防止其他程序集能够创建一个,protected允许派生类甚至在另一个组装来创建它。

    您可以通过更改 getter/setter 来尝试类似的操作(我将它们设为公开/私有,因此创建后它们不能被外部实体修改):

    static void Main(string[] args)
    {
      Car c1 = new Car("Toyota", "Model", "1");
      Console.WriteLine(c1.engine.engineNumber);
    }
    
    public class Car
    {
    
      public class Engine
      {
        public string engineNumber { get; private set; }
        internal protected Engine(string engineNumber)
        {
          this.engineNumber = engineNumber;
        }
      }
    
      public string name { get; private set; }
      public string model { get; private set; }
      public Engine engine { get; private set; }
    
      public Car(string name, string model, string engineNumber)
      {
        this.name = name;
        this.model = model;
        this.engine = new Engine(engineNumber);
      }
    
    }
    

    如果你希望在引擎坏了的情况下能够改变引擎,那么类可能没有嵌套。

    【讨论】:

    • 可能应该指出,在类中包含类通常不是正确的方法,尤其是在这种似乎没有理由的情况下。
    • 可能取决于Engine 是否是更大战略的一部分...Engine 是否真的是一个接口,基于气缸、吸气、排量、HP 等? Engine(或IEngine)如何工作的基本逻辑重要吗?
    • 将类放在自己的文件中通常是构建事物的首选方式。您正在做出一个很大的假设,即 Engine 类将永远不会被 Car 以外的任何东西所需要(也许 OP 也是如此)。这就是为什么它似乎是 OP 的一个很好的学习机会
    • 我问的问题不是关于特定问题的。我刚刚开始学习编程,我想出了是否可以做类似的事情的想法,但是在文档中我无法回答这个问题
    猜你喜欢
    • 2020-08-14
    • 2013-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-05
    • 1970-01-01
    相关资源
    最近更新 更多