有啥理由不使用“受保护”的属性吗?

Posted

技术标签:

【中文标题】有啥理由不使用“受保护”的属性吗?【英文标题】:Is there any reason not to use 'protected' properties?有什么理由不使用“受保护”的属性吗? 【发布时间】:2011-06-19 06:58:22 【问题描述】:

只是想知道...

有什么理由不使用受保护的属性吗?

我的意思是不要使用这个:

public abstract class Foo

    protected Bar  get; private set; 

使用这个:

public abstract class Foo

    private Bar _bar;

    protected Foo(Bar bar)
    
        _bar = bar;
    

    protected GetBar()
    
        return _bar;
    

【问题讨论】:

第二个是完全有效的Java;因此,如果您看到这样的 C# 代码,最可能的原因是它是由尚未真正适应 C# 的 Java 程序员编写的。 您使用protected 来获取可访问性,它与属性无关。 【参考方案1】:

问题不在于protected,它还有更多内容:我为什么要使用属性?

属性在逻辑上与 Getter/Setter 方法对是等价的,无论你可以使用 Name get \ set 对 a 做什么,你都可以使用 GetName() \ SetName() 对,反之亦然,特别是因为 C# 有 getter 和 setter 访问器,所以我们可以也可以使用可访问性。

但是,有些人认为从 OOP 的角度来看,公共(或受保护的)属性有点像作弊,特别是如果该属性所做的只是公开一个支持字段。毕竟person.Name = "SWeko" 似乎在外部改变了对象的状态,而person.SetName("SWeko") 只是告诉对象它需要改变它的状态。从纯理论的角度来看,我认为这些反对意见是有道理的。

但是,并非所有人都拥有生活在象牙塔中的奢侈,因此属性的概念非常有用,因为它更具可读性,更不容易出错,而且恕我直言,更接近现实世界的模型。当我写这样的东西时,它也为我们提供了一种二分法:

person.Name = "SWeko";
person.Work();

我希望第一行将快速分配,并且不会产生副作用,而我希望第二行会做更多的事情,并且可能会影响对象的内部状态。当我使用 Getter 和 Setter 方法时,没有明显的区别:

person.SetName("SWeko");
person.Work();

【讨论】:

恕我直言,读写属性应该表现得像变量。如果一个对象实现了一些读写属性,写入它们然后以任何顺序读取它们而没有任何干预方法调用应该会导致它们读回写入的值。我对可写属性更改只读属性的值,或者方法调用更改任何或所有属性的值(只读或读写)没有问题,但我不喜欢相互连接的读写读写特性。恕我直言,像 StringBuilder.Length 这样的东西应该是一个只读属性,与 SetLength 方法配对。 @supercat 使用 UI 控件会变得非常乏味,因为它们往往具有大量以预期和逻辑方式相互依赖的属性(例如 AutoSize 会影响 Width 和 Height 属性)。 @SWeko:我认为 Forms 的某些部分缺少的一个范式,这将有助于提高其实用性,即“设置”属性与“当前行为”的分离。例如,“Visible”应拆分为“RequestedVisibility”和“IsShown”。 “RequestedVisibility”应该是一个始终返回写入值的读写属性; “IsShown”应该是一个只读属性,指示控件及其所有父级是否设置了 RequestedVisibility。对于大小,应该有请求大小和实际大小属性,前者读写后者只读。 @SWeko:拥有将对象的当前状态复制到“请求”状态的方法,以及从 UI 编辑器中调用此类方法的方法当然很有用;我可以接受,如果没有这样的功能,人们可能不得不对属性做一些丑陋的事情,以使 UI 编辑器工作得很好。然而,尽可能多地根据正交属性定义事物将有助于避免在序列化和反序列化对象时出现问题。 @Supercat:同样,从理论上讲,这种方法是有优点的,因为它将是一个更简洁的设计,但与预期的(并且非常真实的)人类世界观不匹配。更不用说仅仅显示你的表单就需要大量的代码。【参考方案2】:

我看不出有任何理由为什么你会使用 GetXXX() 方法而不是属性,而不管它的修饰符是什么。

由于您使用C# 标签标记了这个问题,我强烈建议使用第一种方法。这就是属性的用途。

只有当每次调用它返回的值都不同时才使用方法,而不管它的状态如何。例如,DateTime.Now 是一个错误,应该是一个方法。

更多详情请参阅属性Usage Guidelines on MSDN。顺便说一句,令人惊讶的是,自从Framework 1.1 以来,他们不需要更改它。

【讨论】:

正如 ammoQ 上面提到的,这可能是从 Java 移植的代码或 Java 程序员的工作——这是 Java 的标准。 并不要求属性必须是幂等的。它应该是“纯的”,没有副作用。 @leppie:如果您查看指南,列表中有一个应该使用的方法,上面写着Calling the member twice in succession produces different results.。当然,它也提到了没有副作用。【参考方案3】:

使用属性而不是方法的更多理由:

数据绑定只能看到属性 您可以使用只读或只写语义。

【讨论】:

【参考方案4】:

仅当您在类中具有不可写或不可读的属性时

【讨论】:

以上是关于有啥理由不使用“受保护”的属性吗?的主要内容,如果未能解决你的问题,请参考以下文章

使用 if(1 || !Foo()) 有啥理由吗?

今天有啥理由不使用 <script defer> 吗?

从 Java 8 开始,有啥理由写 `new Random()` 吗?

有啥理由用同步集合初始化实体属性?

有啥理由不对函数使用 INLINABLE pragma 吗?

有啥理由这不是冗余代码吗?