重复的私有成员变量优于共享的受保护成员

本文关键字:成员 受保护 于共享 共享 变量 | 更新日期: 2023-09-27 18:01:27

这是我最近在c#代码库中注意到的一个习惯用法:

class Base
{
   private readonly MemberClass _memberVariable;
   public Base(MemberClass memberValue)
   {
       _memberVariable = memberValue;
   }
   // methods accessing memberVariable...
}
class Derived : Base
{
   private readonly MemberClass _memberVariable;
   public Derived(MemberClass memberValue) : base(memberValue)
   {
       _memberVariable = memberValue;
   }
   // methods accessing memberVariable...
}

基类及其派生类都有一个成员变量,该成员变量在各自的构造函数中初始化,但不是在基类中将成员声明为protected并在其子类中可用,而是每个子类都有自己的private成员副本。

我的第一反应是,这是一个不必要的重复。再考虑一下,我觉得重复可能是合理的,因为它减少了基类和派生类之间的耦合量,并防止基类的更改导致其子类的意外中断。

protected成员在c#中"被认为是有害的"吗?

重复的私有成员变量优于共享的受保护成员

我会认为受保护的字段是有害的——如果值总是相同的话,我也会认为数据重复是有害的。但是,基类可以通过属性公开私有字段的值:

class Base
{
   private readonly MemberClass memberVariable;
   protected MemberClass MemberProperty { get { return memberVariable; } }    
   public Base(MemberClass memberValue)
   {
       this.memberVariable = memberValue;
   }
   // methods accessing memberVariable or MemberProperty...
}
class Derived : Base
{
   public Derived(MemberClass memberValue) : base(memberValue)
   {
   }
   // methods accessing MemberProperty...
}

在c# 6中,基类变得更简单:

class Base
{
   protected MemberClass MemberProperty { get; }    
   public Base(MemberClass memberValue)
   {
       this.MemberProperty = memberValue;
   }
   // methods accessing MemberProperty...
}

这仍然是一个受保护的属性,由一个私有的只读字段支持——只是编译器为你做了所有的样板文件。

在c#中被保护的成员是"有害的"吗?

一般成员?不,当然不。在c#代码中使用protected成员有很多很好的理由。

此外,我认为你在例子中使用的代码显然是坏的。始终拥有完全相同值的两个副本是浪费的,如果有的话,很可能会产生bug(一旦您有两个应该具有相同值的字段,那么这些值现在就有可能不相同,从而在某处破坏一些代码)。


至于protected 字段的问题?我不同意Jon的观点,至少在某种程度上:对于readonly字段,我认为在某些情况下它是完全好的。

在属性中封装这样一个字段的主要原因是,以后可以详细阐述实现,而不必重新编译相关代码(假设代码在不同的程序集中)。

但是在我看来,这样一个领域很可能永远不需要详细说明其实现。这些字段通常用作常量值的源。比返回字段值更复杂的getter虽然并不罕见,但也不是那么常见(我能想到的最大例外是惰性初始化值)。

目前,我们大多数人都在使用c# 5或更早的版本,而且这种情况可能会持续一段时间。在c# 6语法广泛使用之前,我想说,在某些特定场景中,使用readonly protected字段是对简洁性的一个很好的让步,而不会造成主要的维护/正确性危害

当然,代码越复杂,好的、安全的抽象就越有用,您也就越有可能坚持使用真正封装的只读属性。

但是作为一个绝对的规则?不,我认为没有必要全面禁止readonly protected字段。