应该在类中引用属性还是成员变量

本文关键字:成员 变量 属性 引用 | 更新日期: 2023-09-27 17:55:21

可能的重复项:
是否应该通过属性访问同一类中的变量?

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

我的意思是,无论您是直接访问成员变量还是通过属性(除非您需要躲避一些自定义 setter 代码),这真的不应该有什么区别,但我想确保没有最佳实践。

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";
    }
}

应该在类中引用属性还是成员变量

这不应该是你真正做出的选择。 资源库中的代码要么应该运行,在这种情况下使用属性,要么不运行,在这种情况下使用成员变量。 在大多數情況下,一個是對的,一個是錯的。 在一般情况下,两者都不总是对/错的,而且"无关紧要"是不寻常的。

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

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

这个问题争论很大,所以这个问题没有明显的答案。

就个人而言,我更喜欢通过该属性访问,因为您可能在其中有一些验证或转换代码。即使你的getter和setters是微不足道的,他们将来可能会改变。

如果您将字段foo包装在属性Foo中,则可能是出于某种原因(转换、事件、验证等)。因此,一般来说,您应该引用字段foo的唯一位置是属性Foo的getters和setters。代码的其余部分应引用属性Foo

我敢肯定,存在一些晦涩的情况,您需要绕过属性的获取者和设置者,这当然是可以的,但这种情况将是规则的例外。

选项

1 是一种很好的做法。 因为如果您使用选项 2,则在设置 foo 值时会丢失其他内容。

我会选择选项 1。 如果要设置变量,则应使用该属性,而不是直接访问该变量。 这是因为该物业有你用"//我做其他事情"指示的额外代码。 您不想仅仅因为您没有设置属性而重复这些"其他内容"......除非,您不想在这次设置时执行"其他操作"。

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

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

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

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

如果 setter 有逻辑,则私有变量应该只在 setter 中使用,而永远不要在 setter 之外修改。在任何情况下(在我看来:)),私有变量永远不应该出现在属性setter旁边的其他任何地方。

想象一下这样的代码

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;
}

在此 conext 中,该属性不仅用作变量,还用作其他要执行的操作。访问同一类中的属性并不被认为是一个糟糕的做法,此外,编译器会建议:

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

顺便说一下,您可以将访问成员变量目录的描述更正为直接访问成员变量(即使用字段访问)。