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

Are duplicated private member variables preferable to a shared protected member?

这是我在最近处理的 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...
}

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

我对此的第一反应是这是不必要的重复。再考虑一下,我觉得重复可能是合理的,因为它减少了基础和派生 classes 之间的耦合量,并防止基础 class 的变化导致它的无意破坏subclasses.

C# 中是否有 protected 成员 "considered harmful"?

我认为 protected fields 是有害的 - 如果值应该始终相同,我也会认为数据重复是有害的。但是,基础 class 可以通过 属性 公开私有字段的值:

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 变得更简单:

class Base
{
   protected MemberClass MemberProperty { get; }    

   public Base(MemberClass memberValue)
   {
       this.MemberProperty = memberValue;
   }

   // methods accessing MemberProperty...
}

这仍然是受保护的 属性,由私有只读字段支持 - 只是编译器为您完成了所有样板文件。

Are protected members "considered harmful" in C#?

一般会员?不,当然。在 C# 代码中有 protected 个成员有很多充分的理由。

此外,我认为您在示例中使用的代码显然已损坏。始终拥有完全相同值的两个副本是一种浪费,如果有的话,很可能会产生错误(只要你有两个应该具有相同值的字段,你现在就有机会让这些值不相同,因此最终在某处破坏了一些代码。


至于 protected fields 的具体问题?我在这里不同意 Jon 的意见,至少在一定程度上:对于 readonly 领域,恕我直言,在某些情况下它完全没问题。

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

但是恕我直言,这样的字段很可能从不需要对其实施进行详细说明。这些字段通常用作常量值的来源。一个 getter 比返回一个字段值更复杂的东西虽然不是很罕见,但也不是很常见(我能想到的最大的例外是延迟初始化值)。

目前,我们中的大多数人都在使用 C# 5 或更早版本,这可能会持续一段时间。在 C# 6 语法广泛可用之前,我会说使用 readonly protected 字段是对简洁性的一个很好的让步,没有重大 maintenance/correctness 危险 在某些特定情况下 .

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

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