【问题标题】:Should you use accessor properties from within the class, or just from outside of the class? [duplicate]您应该使用类内的访问器属性,还是只使用类外的访问器属性? [复制]
【发布时间】:2009-01-24 13:32:29
【问题描述】:

我有一个使用 getter 访问某个数组的类“数据”。如果数组为null,那么我希望Data访问文件,填充数组,然后返回具体值。

现在这是我的问题:

在创建 getter 和 setter 时,您是否也应该使用与访问该数组的方式相同的访问器属性(在这种情况下)?还是应该直接访问数组?

我在使用类中的访问器时遇到的问题是,当调用类在 Data.array 中查找一些信息时,我得到了无限循环,getter 发现数组为空,因此从文件中获取它,并且该函数最终再次从 Data 中调用 getter,数组再次为 null,我们陷入了无限循环。

编辑:

所以没有官方对此的立场吗?我看到了不使用带有文件访问权限的访问器的智慧,但是你们中的一些人说总是在类中使用访问器,而另一些人说永远不要使用类中的访问器...... ....................................

【问题讨论】:

    标签: c# .net


    【解决方案1】:

    我同意 krosenvold,并想概括一下他的建议:

    不要将属性 getter 和 setter 用于昂贵的操作,例如读取文件或访问网络。对昂贵的操作使用显式函数调用。

    通常,该类的用户不会期望简单的属性检索或分配可能会花费大量时间。

    This is also recommended in Microsoft's Framework Design Guidelines.;

    一定要使用方法,而不是 属性,在以下情况下。

    操作是数量级的 比字段集慢。如果 您甚至正在考虑提供一个 操作的异步版本 为了避免阻塞线程,它是 很可能是手术太 昂贵的财产。在 特别是,访问 网络或文件系统(除了 一次用于初始化)应该最 可能是方法,而不是属性。

    【讨论】:

      【解决方案2】:

      我认为始终使用访问器是个好主意。那么如果你在获取或设置属性时需要任何特殊的逻辑,你就知道一切都在执行那个逻辑。

      您可以发布这些属性之一的 getter 和 setter 吗?或许我们可以帮忙调试一下。

      【讨论】:

      • 那么我应该设法设置 getter 和 setter,这样它们就不会导致无限循环......
      • 对 - 很难想象为什么会检索数据的函数应该调用 getter - setter 确实如此。
      • 想象力有时非常有限。 --> 确实如此。
      【解决方案3】:

      我写了一个打开文件的getter,后来总是后悔。现在,我永远不会通过 getter 期间的懒惰构造来解决这个问题。有一个带有副作用的 getter 问题,人们不期望在 getter 后面会发生各种疯狂的活动。此外,您可能必须确保线程安全,这会进一步污染此代码。每次执行此操作时,单元测试也会变得稍微困难​​一些。

      显式构造是比各种惰性初始化 getter 更好的解决方案。这可能是因为我使用的 DI 框架将所有这些作为标准使用模式的一部分提供给我。我真的尽量把构造逻辑处理清楚,不要隐藏太多,这样代码更容易理解。

      【讨论】:

      • 所以我可以从调用代码中执行类似的操作: if (class.isNull()) then class.Load() , class.[index]
      【解决方案4】:

      没有。我不相信你应该这样做,原因:可维护的代码。

      我看到人们在定义类中使用属​​性,起初看起来不错。然后其他人出现并为属性添加功能,然后其他人出现并尝试更改类,他们不完全理解类并且所有地狱都崩溃了。

      这不应该是因为维护团队应该完全了解他们想要更改的内容,但他们经常关注不同的问题或错误,而封装的属性通常会忽略它们。我经常看到这种情况,所以从不在内部使用属性。

      它们也可能是性能问题,如果有人将数据库代码放入属性中,那么本应简单的查找可能会变得令人讨厌 - 我也看到人们这样做!

      这么多年过去了,KISS 原则仍然有效……!

      【讨论】:

      • 该死。好点子。现在我不确定该选择哪个选项。
      【解决方案5】:

      除了其他人提出的观点之外,是否直接使用访问器或字段可能需要通过语义来告知。有时,外部消费者访问属性的语义不同于通过内部代码访问其值的机械必要性。

      Eric Lippert 最近在几篇博文中就这个主题发表了博文:-

      automatic-vs-explicit-properties
      future-proofing-a-design

      【讨论】:

        【解决方案6】:

        如果使用 Get 方法导致此类错误,则应直接访问该值。否则,最好使用访问器。如果您应该修改 getter 或 setter 以在将来执行特定操作,如果您未能使用该路径,则会破坏您的对象。

        【讨论】:

        • 我明白这一点,因此我感到困惑。我想我只需要从 getter 中取出 Load(file),并让调用者在访问之前手动调用 Load。
        【解决方案7】:

        我猜你试图实现的是某种延迟加载属性,你只在第一次访问数据时加载数据。

        在这种情况下,我会使用以下方法来防止无限循环:

        private MyData _data = null;
        
        public MyData Data
        {
          get
          {
            if (_data == null)
              _data = LoadDataFromFile();
            return _data;
          }
        }
        
        private MyData LoadDataFromFile()
        {
          // ...
        }
        

        换句话说:

        • 不要实现设置器
        • 始终使用属性访问数据(切勿直接使用字段)

        【讨论】:

        • 这几乎就是我所拥有的,除了 Load() 在自身上循环。我相信我可以用一种可以消除这个问题的方式来编写它。
        【解决方案8】:

        您应该始终使用访问器,但是从文件中读取值的函数(应该是私有的,并且调用类似 getValueFromFile 的东西)应该只在必须读取值时调用从文件中读取,应该只读取文件并返回值。该函数在另一个类中可能会更好,专门用于从您的数据文件中读取值。

        【讨论】:

          【解决方案9】:

          如果我的理解正确,您正在尝试从其实现中访问属性(通过使用在属性的实现代码中调用相同属性的方法)。我不确定是否有任何官方标准,但我认为这是一种不好的做法,除非有特定的需要这样做。

          我总是更喜欢在类中使用私有成员而不是属性,除非我需要属性实现提供的功能。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-07-04
            • 2017-04-15
            • 2015-08-18
            相关资源
            最近更新 更多