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

时间:2009-04-22 19:24:09

标签: c# properties field

我有一个像这样的基类:

 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;
        }
    }
}

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

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

6 个答案:

答案 0 :(得分:12)

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

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

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

答案 1 :(得分:5)

作为最佳做法,您的班级字段应标记为私有 并包含在getter / setter属性中

所以而不是

protected object m_commandArgument;

使用

private object m_commandArgument;

protected object CommandArgument {get; set;}

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

e.g。

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

答案 2 :(得分:4)

FxCop的建议是合理的。您不希望将受保护的字段公开给派生类direclty。由基类管理的状态应该由基类管理 - 永远不会被任何派生类直接修改。

答案 3 :(得分:1)

使用属性。将成员变量更改为private,然后为每个成员变量设置受保护的属性。

的问候,
弗兰克

答案 4 :(得分:0)

基本上,FxCop建议您应该

private object m_commandArgument;

protected object CommandArgument
{
   get { return m_commandArgument; }
   set { m_commandArgument =value}
}

这是基于OO封装规则 - (三个OO规则之一)。您可能希望在分配之前检查值,并且您希望确保派生类不会直接操作它。

答案 5 :(得分:0)

Paul Alexander是正确的,FxCop也是如此。

您希望将字段设为私有,并通过属性公开它们,以防止派生类自行更改变量。强制它们通过属性使基类有机会验证和/或拒绝任何修改。