在类的内部,调用私有成员还是公共属性更好?

11

这是我在代码中一直面临的问题。假设我们有以下代码:

public class MyClass {
    private string _myVariable;

    public string MyVariable {
        get { return _myVariable; }
        set { _myVariable = value; }
    }

    public void MyMethod() {
        string usingPrivateMember = _myVariable; // method A
        string usingPublicProperty = MyVariable; // method B
    }
}

哪种方式更正确-方法A还是B?我总是在这方面犹豫不决。方法A似乎会稍微快一点,因为它不需要在获取真正的变量之前访问属性。但是,方法B更安全,因为如果MyVariable的getter增加业务逻辑,通过始终调用它,即使没有当前业务逻辑,也可以保持安全。

一般有什么共识吗?


https://dev59.com/P3I_5IYBdhLWcg3wDOrW 的内容如下: - Marcel Gosselin
1
谢谢你找到了那些内容!我尝试过搜索,但是可能没有使用正确的关键词。 - Amberite
1
SO的搜索仍然非常差,你试过用Google和'site:stackoverflow.com'吗? - Ash
5个回答

12

使用属性。

我认为该属性应该完全负责管理该字段。

有许多实现情况不会受到影响,但也有很多实现情况会受到影响--而且会受到很大的影响。此外,这可能有点麻烦,因为它看起来总是正确的。

相对于调用该字段,调用该属性所犯错误要少得多,并且在有例外情况时,请记录理由。


使用属性的优点是可以在每次读/写操作时设置断点。这在处理大型、不熟悉的代码库时特别有用。它允许您在调试器中跳过大块的代码,但仍然在属性被修改时停止。非常方便。 - Mike Thompson
在使用存根进行单元测试时,它也可以非常方便,因为您可以在存根属性上设置一个值,但不能在私有成员上设置。 - Jay

1

这真的取决于您访问属性的目的。考虑以下两种情况:

情况1:您编写一个方法来对类中的数据执行常见操作:

// assume a hypothetical class Position

public class Circle
{
    private int _radius;
    private int _xpos;
    private int _ypos;

    public int Radius { get { return _radius; } }
    public Position Center { get { return new Position(_xpos, _ypos); } }

    public bool PointInCircle(Position other)
    {
         return distance(this.Center, other) < this.Radius;
    }
}

明显地,PointInCircle的行为应该与用户在其中执行代码的行为相同。因此,使用公共属性是有意义的。

场景2:您编写一个方法来操作底层数据。这方面的一个很好的例子是序列化。您需要将底层数据成员序列化,而不是通过属性访问器返回的值。


1

这取决于您是否访问该属性,如果访问,则可能会调用“验证”代码。

private int timeSinceLastPropertyAccess;

public int TimeSinceLastPropertyAccess
{
   get 
   { 
      // Reset timeSinceLastPropertyAccess to 0
      int a = timeSinceLastPropertyAccess; 
      timeSinceLastPropertyAccess = 0; 
      return a; 
   }
}

你想在类内部使用 timeSinceLastPropertyAccess 时重置它吗?

这是相当糟糕的getter设计。Get方法不应修改状态。 - Anon.
确实如此,但这表明如果使用getter可能会产生不良影响。 - PostMan
2
考虑到我们正在讨论的是在具有这些属性的同一类中。因此,无论getter是否足够糟糕以产生重大副作用完全取决于您自己的选择。 - Anon.
好的,这是一个更好的例子,在这里它应该重置。 - PostMan

1

只是想再补充一点,你的例子只涉及到了getter。这个问题的另一半是setter。

有时候你会希望对象使用setter,有时候你可能希望它绕过setter直接赋值给底层字段。

例如,假设你有一个名为IsModified的属性,它会告诉你对象是否已被修改。当底层字段中的不同值被赋给该属性时,你可以让所有的setter将其设置为true。

现在,如果你正在填充该对象(从数据库或其他地方加载),那么你就不希望IsModified被设置。因为,坦白地说,它还没有被修改。所以在那个方法中,你使用底层字段名称,但在所有其他方法中,你使用属性setter。


0

这要看情况,你想做属性的事情吗?私有/公共并不重要,就像调用一个函数一样。

实际上,你只是在预期需要在访问或更改该值时执行某些操作而设置了一个“函数”。

这样做的问题在于,你可能会发现在某些地方访问它时想要做一件事,在其他地方访问时又想要做另一件事,因此你仍然需要更改所有对它的“调用”之一。

事实是,如果访问该变量的所有内容(甚至是私有类函数)都是通过只传递变量的属性进行的,那么为什么还要拥有该属性呢?为什么不只创建名为“MyVariable”的变量,然后如果你发现想要在其更改/访问时执行某些操作,只需创建另一个名为“_MyVariable”之类的变量,然后将MyVariable更改为_MyVariable的属性即可。

在编程中,您应该将属性视为与您曾经编写的访问器(accessor())和更改器(mutator())函数完全相同。它们的诀窍是,如果您发现每当访问变量时都需要执行某些代码,则必须更改对该变量的所有调用以使用访问器(调用函数而不仅仅是访问成员变量)。这就是为什么您要创建“默认”访问器和mutador的原因,以防万一。正如我上面所述,您不会遇到此问题,除非您使用C#和属性(除非在一个懒惰的情况下,如果其是属性,则无法编写成员的子成员......为什么?)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接