2009-11-09 44 views
5

在Visual Studio 2008 Team System中,我刚刚在我的一个C#项目上运行了Code Analysis(来自Analyze菜单)。其中产生的警告是以下几点:C#保护字段私有,添加属性 - 为什么?

Microsoft.Design:因为现场“Connection._domain”是它的声明类型的可见外,它的辅助功能更改为私人和添加属性,使用相同的可访问性的字段目前已提供对其的访问。

它指的是以下字段:

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. 它为什么要我这样做?
+0

另请参阅http://stackoverflow.com/questions/1410645/are-public-fields-ever-ok,http://stackoverflow.com/questions/480627/why-wont-anyone-accept-public-fields -in-c,http://stackoverflow.com/questions/1277572/should-i-use-public-properties-and-private-fields-or-public-fields-for-data和其他几个(搜索公共田)。他们都讨论公共领域,但通常也适用于受保护的领域。 – 2009-11-09 20:09:07

回答

13

是的,我想你理解正确的 - 虽然在C#更高版本,还有把它写一个更简洁的方式:

public string Domain { get; set; } 

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

+0

在他的情况下,'protected string Domain {get;组; }' – nawfal 2013-06-03 17:05:49

2

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

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

2
  1. 是的,你确实纠正了代码明智的问题。
  2. 这是关于封装。 _domain是关于你的对象的数据。而不是直接暴露它,以便任何客户端都有未经过滤的访问,您应该提供一个接口让他们访问它。实际上,这可能会增加对setter的验证,因此它不能设置为任何值。如果你是唯一编写代码的人看起来很愚蠢,因为你知道你的API是如何工作的。但是尝试在大型企业层面上考虑事情,最好是有一个API,这样你的对象可以被看作是一个可以完成任务的盒子。你可能会说你永远不会需要为这个对象添加一些类似验证的东西,但是事情的完成就是为了保持它的可能性,并且要保持一致。
2

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

将所有字段保留为私有并将其包装在属性中以便您可以选择在将来添加验证或其他逻辑而不重新编译您的类的所有使用者(或本例中为继承者)是一种好的做法。

+0

为什么downvote?从技术上讲,这是事实。访问字段的IL与访问权限时不同。如果编译引用不同装配体(B)中的字段的装配体(A),然后更新装配体(B)并将字段更改为属性,则装配体(A)将被破坏。 – Bob 2009-11-09 20:11:40

+0

我同意鲍勃,我认为这是一个非常重要的考虑因素。 (+1)将字段更改为属性(因为您希望添加验证逻辑或日志记录或希望使其变为虚拟或任何其他可能存在的原因)对该类的任何用户都是一个二进制重大更改。如果您将字段的名称命名为小写字母和属性大写,那么它也可能是源代码级别的中断,正如惯例。 – Joren 2009-11-09 20:18:00

+0

这就是你应该使用属性的原因。如果情况并非如此,那么在你决定需要它们之前,没有理由使用属性。我以为回答了这个问题/耸耸肩:) – GraemeF 2009-11-09 20:21:08

2

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

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

protected string Domain { get; set; } 
0

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

不过,我只想用自动属性语法:

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

除了这里提到的其他答案,即以下划线开头的公共/ protected成员不CLS-compliant,在那里是.NET语言的支持与领先的下划线成员没有要求,所以有人以不同的.NET语言从您的类继承可能无法访问该特定的受保护成员。

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