重复的私有成员变量优于共享的受保护成员
本文关键字:成员 受保护 于共享 共享 变量 | 更新日期: 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
字段。