C#protected field to private,添加属性 - 为什么?

时间:2009-11-09 20:02:14

标签: c# static-analysis access-levels

在Visual Studio 2008 Team System中,我刚刚在我的一个C#项目上运行了Code Analysis(来自Analyze菜单)。产生的警告之一如下:

  

Microsoft.Design:因为字段'Connection._domain'在其声明类型之外是可见的,所以将其可访问性更改为private并添加一个属性,具有与当前字段相同的可访问性,以提供对它的访问。

它指的是以下字段:

public abstract class Connection
{
    protected string _domain;
}

我不明白这个建议背后的原因。这是我认为它要我做的事情:

public abstract class Connection
{
    private string _domain;
    protected string Domain { get { return _domain; } set { _domain = value; } }
}

两个问题:

  1. 我是否正确理解了建议要求我做什么,代码明智?
  2. 为什么要我这样做?

8 个答案:

答案 0 :(得分:13)

是的,我认为您理解正确 - 尽管在C#的更高版本中,有一种更简洁的方式来编写它:

public string Domain { get; set; }

为什么呢?这都是关于封装的。如果按照建议执行操作,则可以稍后更改Domain属性的定义,而不会影响使用该属性的任何调用代码。由于您的课程是公开的,并且可能会被您没有编写的代码调用,这可能非常重要。

答案 1 :(得分:2)

是的。这是建议。您不应该具有比作为直接实例字段公开的私有高的任何可访问性。

这是OOD的主要原则之一 - 封装也被称为“数据隐藏”。

答案 2 :(得分:2)

  1. 是的,您确实修正了问题代码。
  2. 关于封装。 _domain是有关您对象的数据。而不是直接暴露它以便任何客户端都有未经过滤的访问,您应该为它们提供访问它的接口。实际上,这可能是为setter添加验证,因此无法将其设置为任何值。如果你是唯一一个编写代码的人,那可能看起来很愚蠢,因为你知道你的API是如何工作的。但是,尝试在大型企业级别上考虑事情,最好有一个API,以便可以将您的对象视为容纳任务的框。您可能会说您永远不需要为该对象添加诸如验证之类的东西,但事情是以这样的方式来保持它的可能性,并且也是一致的。

答案 3 :(得分:2)

这是因为如果您以后想要将字段更改为属性,则会破坏依赖于该属性的任何其他程序集。

优良作法是将所有字段保密并将其包装在属性中,以便您可以选择在将来添加验证或其他逻辑,而无需重新编译类的所有使用者(或者在本例中为继承者)。

答案 4 :(得分:2)

您的翻译是正确的。对于使用'protected'属性可以使用'public'属性而不是直接暴露成员变量,可以使用相同的参数。

如果这只会导致简单的getter和setter的扩散,那么我认为代码可读性的损害超过了将来能够更改代码的好处。随着C#中编译器生成的属性的发展,这并不是那么糟糕,只需使用:

protected string Domain { get; set; }

答案 5 :(得分:0)

回答你的问题......是的。

但是,我只想使用自动属性语法:

public abstract class Connection
{
    protected string Domain { get; set; }
}

答案 6 :(得分:0)

基本上,属性提供的不仅仅是返回或设置成员。它们允许您添加可以验证正确输入格式,范围验证等的逻辑。

链接中选定的答案最好,“属性提供封装。您可以在属性的代码中包装任何所需的验证/格式化/转换。这对字段很难。”

http://social.msdn.microsoft.com/Forums/en-IE/netfxbcl/thread/985f4887-92ae-4ec2-b7ae-ec8cc6eb3a42

答案 7 :(得分:0)

除了这里提到的其他答案之外,以下划线开头的公共/受保护成员不是CLS-compliant,因为不需要.NET语言来支持具有前导下划线的成员,所以有人继承您使用不同.NET语言的类可能无法访问该特定受保护成员。

我知道,它可能不适用于您,但它可能是代码分析警告的部分原因。