【问题标题】:C#3.0 Automatic properties, why not access the field directly?C#3.0 自动属性,为什么不直接访问字段呢?
【发布时间】:2008-10-06 13:07:54
【问题描述】:

使用在类的属性中获取/设置的新方法:

public string FirstName {
        get; set;
    }

为什么不简单地将属性 FirstName 设为 public 而不使用访问器?

【问题讨论】:

标签: c#-3.0 properties


【解决方案1】:

直接访问类内部变量(字段/属性)的两个大问题是:

1) 您不能轻松地对字段进行数据绑定。

2) 如果您从类中公开公共字段,则以后不能将它们更改为属性(例如:向设置器添加验证逻辑)

【讨论】:

  • 我认为第 2 点非常次要,除非您碰巧正在编写类似 .NET 框架本身的东西。更改库并期望在不将应用程序重新编译到客户端的情况下推送更新的库并不常见 - 如果您正在处理内部类型(首先是大多数类型),则该参数在第一名。
【解决方案2】:

因为,将来,如果您更改实现,使用当前接口的代码不会中断。

例如,您实现了一个带有公共字段的简单类,并开始在一些外部模块中使用您的类。一个月后,您发现需要在该类中实现延迟加载。然后,您需要将该字段转换为属性。从 ciew 的外部模块来看,它在语法上可能看起来相同,但事实并非如此。属性是一组函数,而字段是类实例中的偏移量。

通过使用属性,您可以有效地降低界面更改的风险。

【讨论】:

    【解决方案3】:

    这主要归结为它已成为一种常见的编码约定。如果您愿意,可以轻松添加自定义处理代码。但是您是对的,从技术上讲,这没有真正的必要。不过,如果您稍后添加自定义处理,这将帮助您不破坏界面。

    【讨论】:

      【解决方案4】:

      当您混合 getter 和 setter 的可访问性时,这种表示法会更有用。例如,你可以写:

      public int Foo { get; private set; }
      

      您还可以放置一个内部 setter,甚至将 getter 设为私有而将 setter 设为公开。

      这种表示法避免了仅仅为了处理内部可写/外部可读值的经典问题而显式编写私有变量的需要。

      【讨论】:

        【解决方案5】:

        关键是编译器将“幕后”属性转换为函数对,当您的代码看起来像是在使用该属性时,它实际上是在编译为 IL 时调用函数。

        假设您将其构建为一个字段,并在使用该字段的单独程序集中有代码。如果稍后实现发生更改,并且您决定将其设置为对其余代码隐藏更改的属性,则仍需要重新编译和重新部署其他程序集。如果它从一开始就是一个属性,那么一切都会正常工作。

        【讨论】:

          【解决方案6】:

          我认为提问者在问为什么不做以下事情......

          public string FirstName { }
          

          当您可以将访问器缩短为上述内容时,为什么还要打扰访问器。我认为答案是,通过要求访问器使阅读代码的人清楚它是标准的获取/设置。如果没有它们,您可以在上面看到很难发现这是自动实现的。

          【讨论】:

          • 这给出了“属性或索引器必须至少有一个访问器”错误。
          • 这对编译器 { get; } 或 { 设置; } 或 { 获取;内部集;等...缺少访问器意味着没有访问器。
          【解决方案7】:

          当您遇到错误并且需要找出哪些方法正在修改您的字段以及何时修改时,您会更加关心。如果出现涉及您包裹的字段的错误,将轻量级属性访问器放在前面可以节省大量的心痛。我遇到过几次这种情况,感觉并不愉快,尤其是当它被证明与重入有关时。

          提前完成这项工作并在访问器上设置断点比其他方法容易得多。

          【讨论】:

            【解决方案8】:

            对于 99% 的情况,公开一个公共字段是可以的。

            常见的建议是使用字段:“如果您从类中公开公共字段,则以后不能将它们更改为属性”。我知道我们都希望我们的代码是面向未来的,但是这种想法存在一些问题:

            • 当您更改接口时,您的类的使用者可能会重新编译。

            • 99% 的数据成员永远不需要成为重要的属性。这是speculative generality。您正在编写很多可能永远不会有用的代码。

            • 如果您需要跨版本的二进制兼容性,将数据成员添加到属性中可能是不够的。至少,您应该只公开接口并隐藏所有构造函数,并公开工厂(参见下面的代码)。


            public class MyClass : IMyClass
            {
                public static IMyClass New(...)
                {
                    return new MyClass(...);
                }
            }
            

            这是一个难题,试图编写在不确定的未来可以工作的代码。真的很难。

            Does anyone have an example of a time when using trivial properties saved their bacon?

            【讨论】:

            • 是的,很难编写未来的证明代码。因此,您采取了所有可以采取的预防措施,例如使用属性而不是公共字段。它是如此简单,以至于它真的是不费吹灰之力。
            • @Jay Bazuzi:如果您处于项目符号列表的中间,那么代码格式化似乎在 WMD 中不起作用。如果您在列表和代码之间添加任何内容,它将正确格式化。我只是添加了一条水平规则,因为中间没有任何有用的东西。
            【解决方案9】:

            它保留了对象的封装性,减少了代码的可读性。

            【讨论】:

              猜你喜欢
              • 2017-08-31
              • 2014-05-17
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-04-03
              相关资源
              最近更新 更多