【问题标题】:C# protected field to private, add property--why?C# 保护字段为私有,添加属性——为什么?
【发布时间】:2010-12-14 18:34:16
【问题描述】:

在 Visual Studio 2008 Team System 中,我刚刚对我的一个 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. 为什么要我这样做?

【问题讨论】:

标签: c# static-analysis access-levels


【解决方案1】:

是的,我认为你理解正确——尽管在 C# 的更高版本中,有一种更简洁的写法:

public string Domain { get; set; }

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

【讨论】:

  • 就他而言,protected string Domain { get; set; }
【解决方案2】:

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

最好将所有字段保持私有并将它们包装在属性中,以便您可以选择在将来添加验证或其他逻辑,而无需重新编译您的类的所有使用者(或在这种情况下为继承者)。

【讨论】:

  • 为什么投反对票?从技术上讲,这是真的。访问字段的 IL 与访问属性时的 IL 不同。如果您编译一个引用不同程序集 (B) 中的字段的程序集 (A),然后更新程序集 (B) 并将字段更改为属性,程序集 (A) 将被破坏。
  • 我同意,鲍勃,我认为这是一个非常重要的考虑因素。 (+1)将字段更改为属性(因为您想要添加验证逻辑或日志记录或想要使其成为虚拟,或者可能存在的任何其他原因)是对该类的任何用户的二进制重大更改。如果按照惯例将字段命名为小写,属性命名为大写,这也可能是源级别中断。
  • 这就是你应该使用属性的原因。如果不是这种情况,那么在您决定需要它们之前,没有理由使用属性。我认为这回答了问题/耸了耸肩:)
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:
    1. 是的,您确实更正了问题代码。
    2. 这是关于封装的。 _domain 是关于您的对象的数据。与其直接公开它以使任何客户端都具有未过滤的访问权限,不如为他们提供访问它的接口。实际上,这可能会向设置器添加验证,以便不能将其设置为任何值。如果你是唯一一个编写代码的人,因为你知道你的 API 是如何工作的,这可能看起来很傻。但是尝试在大型企业级别上考虑问题,最好有一个 API,以便您的对象可以被视为完成任务的盒子。您可能会说您永远不需要向该对象添加诸如验证之类的东西,但是这样做是为了保持它的可能性,并且也是为了保持一致。

    【讨论】:

      【解决方案5】:

      您的翻译是正确的。使用“受保护”属性的参数与使用“公共”属性而不是直接公开成员变量的参数相同。

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

      protected string Domain { get; set; }
      

      【讨论】:

        【解决方案6】:

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

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

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

        【讨论】:

          【解决方案7】:

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

          从链接中选择的答案最好,“属性提供封装。您可以在属性的代码中封装任何需要的验证/格式化/转换。这对于字段来说很难做到。”

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

          【讨论】:

            【解决方案8】:

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

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

            【讨论】:

              猜你喜欢
              • 2018-01-27
              • 2016-06-04
              • 2018-03-08
              • 1970-01-01
              • 2014-11-03
              • 1970-01-01
              • 1970-01-01
              • 2012-02-11
              • 2019-07-24
              相关资源
              最近更新 更多