【问题标题】:Creating an Accessor Method for Private Object Properties - Enumeration?为私有对象属性创建访问器方法 - 枚举?
【发布时间】:2012-03-20 13:59:10
【问题描述】:

我正在学习访问器方法和枚举。我在命名空间“Vehicles”下编写了一个公共类“Car”,并设置了私有属性,例如_manufacturer、_model、_year 和_color。我想写一个方法来访问属性和另一个来设置/更新它们。这是我的课:

using System;

namespace Vehicles
{
    public class Car
    {
        private string _manufacturer;
        private string _model;
        private string _year;
        private string _color;

        public void honkHorn()
        {
            // Add argument for a file name?
            // Code here to play a WAV file?
            MessageBox.Show("Honk!");
        }

        public string getCarInfo(string whichProperty)
        {
            switch (whichProperty)
            {
                case ("manufacturer"):
                   return _manufacturer;
                case ("model"):
                    return _model;
                case ("year"):
                    return _year;
                case ("color"):
                    return _color;
                default:
                    return null;
            }
        }

        public void setCarInfo(string whichProperty, string newValue)
        {
            switch (whichProperty)
            {
                case ("manufacturer"):
                    _manufacturer = newValue;
                    break;
                case ("model"):
                    _model = newValue;
                    break;
                case ("year"):
                    _year = newValue;
                    break;
                case ("color"):
                    _color = newValue;
                    break;
            }
        }
    }
}

这是我的表格:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Vehicles;

namespace CS_Enumeration
{
    public partial class Form1 : Form
    {
        public Car myCar = new Car();

        public Form1()
        {
            InitializeComponent();

            myCar.setCarInfo("manufacturer", "Ford");
            labelManfValue.Text = myCar.getCarInfo("manufacturer");

            myCar.setCarInfo("model", "Ranger");
            labelModelValue.Text = myCar.getCarInfo("model");

            myCar.setCarInfo("year", "2012");
            labelYearValue.Text = myCar.getCarInfo("year");

            myCar.setCarInfo("color", "Blue");
            labelColorValue.Text = myCar.getCarInfo("color");
        }

        private void button1_Click(object sender, EventArgs e)
        {
            myCar.honkHorn();
        }
    }
}

这真的是编写可以获取/设置的单一方法的最佳方式吗?我首先尝试强制转换与对象属性名称匹配的字符串值并返回实际属性,但这不起作用(除非有人知道如何将字符串转换为对象属性?)。

感谢您的回复。这都是我正在阅读的书中的练习。它甚至说不是所有的东西都应该是公开的,但也不是所有的东西都应该是私有的。那么我怎么知道什么时候应该/不应该公开/私有呢?听起来这本书把我引向了错误的方向,什么是好的编码设计。任何人有任何关于学习良好的 Visual C# 编码设计实践的书籍建议吗?

【问题讨论】:

  • 你为什么要这样做?海事组织这是一个可怕的设计 - 只是暴露属性。最重要的是,您在当前方法中失去了所有类型安全性,任何拼写错误都会导致运行时异常
  • 查看我的原始帖子的编辑。这一切都基于我正在阅读的 C# 书籍,并且建议使用私有变量。我可以从我必须经历的获取/设置属性中看出这有点荒谬。谢谢。
  • 这是什么书?我们想忽略它,并可能嘲笑它。
  • @JohnSaunders Head First C#
  • 谢谢。显然,这是头脑优先,而不是大脑优先。

标签: c# enumeration accessor


【解决方案1】:

不要这样做。

改为使用公共属性,您可以获得类型安全性和类的更具表现力的用法。在您当前的方法中,属性名称字符串中的任何拼写错误都会导致运行时异常而不是编译错误。

只使用属性:

public class Car
{
   public string Manufacturer {get; set;}
   public string Model {get; set;}
   public string Year {get; set;}
   public string Color {get; set;}

  //..
}

现在您可以直接访问属性:

myCar.Manufacturer  = "Ford";
labelManfValue.Text = myCar.Manufacturer;

您还应该定义一个完全初始化 Car 对象的构造函数,否则您可能设置了一些属性,而其他则没有。

【讨论】:

  • 要定义一个构造函数,我只是将属性添加到类定义中,还是与枚举有关?构造函数看起来像public class Car(string manufacturer)
  • 是的——像这样。至于公开/私人辩论-根据您的示例,显然您希望从外部对这些属性进行 读取访问,因此至少是只读属性-而且属性也被编译为 getter/setter 方法相同类型的支持字段 - 这基本上等同于您尝试使用 setter 方法实现的目标。
  • 好的,听起来我想完全按照您在 {get;放;}。我相信即使我没有定义构造函数,当我实例化对象时我仍然可以初始化变量,对吗?类似Car porche = new Car({ _speed = fast; })
【解决方案2】:

你可以通过反射来做到这一点:

void Main()
{
    var foo = new Foo();
    foo.Set("bar","test");
    Console.WriteLine(foo.Get("bar"));
}
class Foo
{
    string bar;
    string bop;

    public void Set(string name, string value)
    {
        GetType().GetField(name, BindingFlags.NonPublic|BindingFlags.Instance)
                 .SetValue(this, value);
    }

    public string Get(string name)
    {
        return (string)GetType().GetField(name, BindingFlags.NonPublic|BindingFlags.Instance)
                                .GetValue(this);
    }
}

但这是一个非常糟糕的主意。

【讨论】:

    猜你喜欢
    • 2018-12-18
    • 1970-01-01
    • 2011-12-09
    • 2019-11-20
    • 2023-03-09
    • 1970-01-01
    • 1970-01-01
    • 2017-03-05
    • 1970-01-01
    相关资源
    最近更新 更多