公开受保护字段的最佳方式

Sun*_*nit 3 c# field properties

我有这样一个基类:

 public class BaseModalCommand
 {

    protected object m_commandArgument;
    protected int m_commandID;
    protected int m_enableUIFlags;

    public virtual void OnIdle()
    {
    }

    public virtual void OnResume()
    {
    }

    public virtual void OnStart(int commandID, object argument)
    {
    }

    public virtual void OnStop()
    {
    }



    public virtual int EnableUIFlags
    {
        get
        {
            return this.m_enableUIFlags;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

虚拟方法将在派生类型中被覆盖.如果我通过FxCop运行它,它会抱怨没有声明可见的实例字段,并建议将其更改为private并将其作为受保护的属性公开.

有什么想法吗?我认为这个消息可以被忽略.

Pon*_*gge 12

对于任何类,客户端代码有两种用法:引用您的类的代码和继承您的类的代码.人们普遍认为,第二种用途是迄今为止最紧密耦合的.你班级的变化直接影响他们的内部机制.这样你暴露保护成员意味着你的基类的变化会影响到你的派生类中是没有比较每个基类和派生类的代码不可预知的方式是如何工作的.同样糟糕的是,派生类可以修改基类的内部.

如果您确实希望公开这样的内部数据成员,请将私有数据成员包装在受保护的属性中(如gisresearch建议的那样).这些属性(以及任何受保护的方法)构成了类的继承接口.就像暴露在外部客户的任何接口(无论是通过定义只,或通过显式接口实现公共方法和属性),该接口是你将需要管理,特别是在较大的代码库.界面可以更改,但应作为有意识的决定进行更改.

如果直接使用受保护的数据成员,则对基类和派生类之间的依赖关系的控制要少得多.相信我:甚至无法确定改变可能产生的影响可能是非常不愉快的事情.


Eoi*_*ell 6

作为最佳实践,您的类字段应标记为私有并包含在getter/setter属性中

而不是

protected object m_commandArgument;
Run Code Online (Sandbox Code Playgroud)

使用

private object m_commandArgument;

protected object CommandArgument {get; set;}
Run Code Online (Sandbox Code Playgroud)

这有几个优点,但简单的用法是在你的setter中进行异常处理/验证.

例如

private string _email;
protected string Email
{ 
   get { return _email; }
   set 
   {
       if(value.IndexOf("@") > 0)
           _email = value;
       else
            throw new ArgumentException("Not a valid Email");
   }
}
Run Code Online (Sandbox Code Playgroud)


Pau*_*der 5

FxCop的建议是正确的。您不想将受保护的字段公开给派生类。由基类管理的状态应由基类管理-切勿直接由任何派生类修改。