【问题标题】:Should you reference the Property or the Member Variable inside a class? [duplicate]您应该在类中引用属性还是成员变量? [复制]
【发布时间】:2013-01-23 17:49:22
【问题描述】:

可能重复:
Should you access a variable within the same class via a Property?

我最近遇到了这个问题,我很好奇是否有某种标准,你应该在课堂上参考哪个标准。

我的意思是,无论您是直接访问成员变量还是通过属性,都应该没有区别(除非您需要避开一些自定义设置器代码),但我想确保没有最佳实践为它。

partial class MyClass {
    private string foo;

    internal string Foo {
        get {
            return foo;
        }

        private set {
            foo=value;
            // I do other stuff
        }
    }

    public void DoSomething() {
        //Option 1;
        Foo="some string";

        //Option 2;
        foo="some string";
    }
}

【问题讨论】:

  • 在某些情况下,使用该属性可能很重要(单例模式可能需要这样做),而在其他情况下可能完全不重要。
  • // I do other stuff 有多重要?如果您直接访问该成员,则 other stuff 不会完成。在这里做这件事是对还是错?除此之外,这是您/您的团队的决定。
  • @O. R. Mapper - 谢谢,显然我需要更新我的 google-fu,尝试搜索但找不到任何接近的东西。
  • @Wrightboy:现在将侧边栏上的另一个问题显示为“相关”部分中的第一项。但我想这在撰写本文时也不可见。

标签: c# .net-4.0 properties


【解决方案1】:

这不应该是你真正做出的选择。 setter 中的代码应该运行,在这种情况下使用属性,或者不应该运行,在这种情况下使用成员变量。在大多数情况下,一种是对的,一种是错的。在一般情况下,两者都不总是对/错,而且“无关紧要”是不寻常的。

例如,如果设置器代码正在触发“已更改”事件,您是否希望通知外部对象它已更改?如果您要更改它以响应先前的更改,可能不会(无限递归任何人?)如果不是,您可能希望确保它被触发(这样您就不会更改值并且不会通知任何人更改)。

如果只是验证所设置的值是否有效,那么您要么知道,在这种情况下,该值已经验证并且必须有效,在这种情况下无需再次验证;设置属性。如果您尚未验证要设置的内容,那么您希望运行验证逻辑,因此请使用该属性。

【讨论】:

  • 但是,您可以假设该值有效的唯一原因是属性中的验证逻辑。一旦您允许绕过该验证逻辑,就不再安全地假设该值有效。 - 就事件而言:在值发生变化时不触发 Changed 事件在某种程度上违反了合同。无限递归通常通过属性中的if 语句来避免(即仅在值实际更改时触发 Changed 事件)。
  • @Ginosaji 至于验证,不,这不是唯一的方法。考虑一下,您有一个函数可以将属性设置为其默认值。您知道默认值是有效值,因此在设置时无需调用验证逻辑。至于事件,那不包括案件。我已经看到了属性更改事件处理程序需要更改该事件的示例。它可能不会导致无限递归,但它至少会触发事件两次,而它应该只触发一次。不过,这个问题还有其他解决方案。
【解决方案2】:

这个问题引起了很多争论,所以这个问题没有明显的答案。

我个人更喜欢通过该属性进行访问,因为其中可能包含一些验证或转换代码。即使您的 getter 和 setter 微不足道,它们也可能在未来发生变化。

【讨论】:

    【解决方案3】:

    如果您将字段 foo 包装在属性 Foo 中,您这样做可能是有原因的(转换、事件、验证等)。因此,一般来说,您应该引用字段foo 的唯一位置是属性Foo 的getter 和setter。其余代码应引用属性Foo。

    我确信存在一些需要绕过属性的 getter 和 setter 的模糊情况,这当然可以,但这种情况是规则的例外。

    【讨论】:

    • 你是对的,我使用了一个属性,因为无论何时访问 foo ,它都需要在返回之前对其进行一些操作(验证/排序)。我通常会通过该属性访问,但由于这种排序等有点昂贵,因此在访问它的类中很多人想要规避这一点,因为它根本不需要。不知道这样做会不会违反任何规则。
    • 我不确定我是否会在 getter 中进行昂贵的排序操作,但假设我会说这是绕过该属性的正当理由。我唯一会说绕过该属性是完全不正确的,是它会导致代码重复。
    • 是的,我确实考虑过只创建一个 GetSortedFoo() 方法,但是在类之外我发现每次使用它都需要对其进行排序,所以我想为什么不直接在财产。
    【解决方案4】:

    选项 1 是很好的做法。因为如果你使用Option 2,你会在设置 foo 值时丢失其他东西。

    【讨论】:

    • 你能解释一下失去其他东西是什么意思吗?选项 1 属性访问器最好不要丢失其他东西。在这种情况下,为什么选项 2 会更好?
    • 我的意思是那些代码不会运行。
    • 太酷了。只是想看看你是否有不同的思路以及背后的原因。
    【解决方案5】:

    我会选择选项 1。如果您要设置变量,则应使用该属性而不是直接访问该变量。这是因为该属性具有您用“// 我做其他事情”指示的额外代码。你不希望仅仅因为你没有设置属性就重复这个“其他事情”......除非你不想在这次设置它时做“其他事情”。

    老实说,这只是一个理论上的情况,如果你给出一个遇到这个问题的实际情况会更容易回答。

    【讨论】:

      【解决方案6】:

      使用 INotifyPropertyChanged 接口时,如果您希望更新绑定对象,则必须使用属性。

      【讨论】:

        【解决方案7】:

        如果设置器没有逻辑,那么显式声明私有变量是没有意义的,最好使用自动实现的属性:

            internal string Foo
            {
                get;
                private set;
            }
        
            public void DoSomething()
            {
                this.Foo = "some string";
            }
        

        如果setter有逻辑,私有变量只能在setter中使用,绝不能在setter之外修改。 无论如何(在我看来:))私有变量不应该出现在属性设置器旁边的任何其他地方。

        【讨论】:

          【解决方案8】:

          想象一下这样的代码

          public partial class HybridPanel: Panel {
              [DefaultValue(BorderStyle.FixedSingle)]
              public virtual new BorderStyle BorderStyle {
                  set {
                      if(value!=borderStyle) {
                          borderStyle=value;
                          base.PerformLayout();
                      }
                  }
          
                  get {
                      try {
                          return borderStyle;
                      }
                      finally {
                          if(borderStyle!=base.BorderStyle)
                              base.PerformLayout();
                      }
                  }
              }
          
              BorderStyle borderStyle=BorderStyle.FixedSingle;
              bool isCollapsed, isAutoSize;
          }
          

          在这种情况下,属性不仅用作变量,还可以做其他事情。 访问同一类中的属性NOT被认为是一种不好的做法,此外,编译器会建议:

          仅用于访问字段而不传递参数的方法,请考虑将其定义为属性。

          顺便把访问成员变量目录的描述改成直接访问成员变量(即通过字段访问)。

          【讨论】:

            猜你喜欢
            • 2012-06-13
            • 1970-01-01
            • 2015-06-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-09-21
            • 1970-01-01
            相关资源
            最近更新 更多