我应该公开类的属性吗?

Should I expose the properties of my classes?

本文关键字:属性 我应该      更新时间:2023-10-16

在我所有的研究中,我了解到当我想让用户访问内部属性时,我不应该直接访问该属性,而是通过get/set方法来访问,例如:

class myClass
{
    private int x;
    public void SetX (int x)
    {
        this.x = x;
    }
    public int GetX ()
    {
        return this.x
    }
}

因为它提供了额外的好处,允许程序员更容易地完全改变引擎而不影响用户,更容易调试,并为检查输入的有效性提供了更多的选项。

然而,自从我开始学习和编写c#以来,我注意到大多数"原生"语言的类都暴露了它们的属性,例如,设置/获取矩形(System.Drawing.Rectangle)的位置或大小,您可以直接访问X, Y, WidthHeight属性。

  • 我认为暴露属性的唯一好处是代码更简单一些。公开属性还有其他好处吗?

  • 什么时候应该公开属性,什么时候不应该?

你混淆了属性和字段。在c#中,属性可以像公共字段一样使用,但是在内部调用它们的get/set方法。例如,带有属性的类看起来像这样:

class MyClass
{
    // Field, direct access to the internal representation
    private int x; 
    // Property, access via methods, but syntax like field access
    public int X {
        get { return this.x; } // generates a get-method "int get_X()"
        set { this.x = value; } // generates a set-method "void set_X(int value)"
    }
}

当你现在像这样设置属性X: myClass.X = 42 时,编译器将其转换为 myClass.set_X(42) ,它调用在 set 块中声明的方法。类似字段的语法只是为了方便。

因此,您确实应该倾向于公开set/get-methods。只是在c#中,首选的方法是通过属性,它抽象了这些方法的实际调用,并允许您像使用字段一样使用它们。

基本上,你的问题是属性vs公共变量。什么时候用什么?

阅读这篇文章,包括评论。

整个讨论的快速总结:

  • 反射在变量和属性上的工作方式不同,所以如果你依赖反射,
    更容易使用所有属性。
  • 你不能绑定一个变量。
  • 将变量更改为属性是一个破坏性的更改。

暴露数据成员的琐碎属性实现是没有或很少有收益的大量代码,只有合理的原因可以:

  • 提供对由于某种原因不能声明为const的成员变量的只读访问

  • 如果你正在编写一个供第三方使用的组件,并且存在任何可能的组件必须被替换而不需要这些用户重新构建(将公共成员变量更改为属性会破坏接口,因此需要重新构建)。

同样,在属性中包装公共字段有两个原因——一个是你不能在不破坏二进制兼容性的情况下更改它。二是不能绑定字段。

Reflection code against fields looks very different from reflection code against 
properties (FieldInfo vs. PropertyInfo for starters). So even if you can 
recompile against the new binary, if you use reflection on that field 
you're hosed.

在c#中,你使用属性而不是getter/setter方法,因为它们提供相同的功能。注意,fields != properties。参见MSDN: Properties.

就像您说的,不直接访问变量的好处是您可以更改实现而不需要对类的用户进行任何更改。在面向对象编程方面,我认为这是一件重要的事情。

另外,通过使用属性,您仍然可以影响"get"或"set"的工作。这在某些情况下是有用的