简体   繁体   English

在内部访问值的正确方法是什么?

[英]What is the proper way to access a value internally?

In the following setter, I can access the property backing field directly or through the getter. 在下面的setter中,我可以直接或通过getter访问属性支持字段。 Is there a scenario when one would be preferred over the other? 是否存在一个比另一个更受欢迎的情况?

public string Name {
        get { return this.name; }
        set {
            if (value == this.name) return;
            // or
            // if (value == this.Name) return;
            // ?
            this.name = value;
            NameChanged.Raise(this, this.name);
            // or
            // NameChanged.Raise(this, this.Name);
            // ?
        }
    }

There is a related question. 有一个相关的问题。 How would you initialize properties in the c-tor? 你会如何在c-tor中初始化属性?

public MyClass(string name) { this.name = name; }
// or
public MyClass(string name) { Name = name; }

I use this.name , for the reason that at construction time the instance might be in an invalid/unstable/undefined state, so Name-setter validation might falsely fail. 我使用this.name ,因为在构造时实例可能处于无效/不稳定/未定义状态,因此Name-setter验证可能会错误地失败。 Any other opinions? 还有其他意见吗?

I would say that "Name = name" is more correct, because if you were to declare the "name" property as virtual then someone could override your property behaviour, but your constructor would still bypass their logic. 我会说“Name = name”更正确, 因为如果你要将“name”属性声明为virtual,那么有人可以覆盖你的属性行为,但你的构造函数仍会绕过它们的逻辑。

Additionally properties can encapsulate behaviour such as raising change events, which you shouldn't bypass. 此外,属性可以封装行为,例如提升更改事件,您不应绕过这些行为。 No user can add a handler to your event until you have constructed the object. 在构造对象之前,任何用户都无法为事件添加处理程序。 Therefore if you make a setting in a constructor where you have external events, it won't be raised. 因此,如果在具有外部事件的构造函数中进行设置,则不会引发该设置。

EDIT 编辑

See the comments below for why virtual was a bad example. 请参阅以下评论,了解为什么虚拟是一个糟糕的例子。

My personal approach to this problem is 我个人对这个问题的处理方法是

Only use a this qualifier when to do otherwise would result in incorrect behavior or a compilation error. 只有在使用此限定符时才会导致不正确的行为或编译错误。

I prefer to make my code readable in the abscence of a this qualifier. 我更喜欢在这个限定符的绝对值中使我的代码可读。 If it's unreadable without a this qualifier I strive to change the code to be readable. 如果没有这个限定符它是不可读的,我会努力将代码更改为可读。

In this case, the difference between the syntax is that in one case the getter/setter get invoked, while in the other case they don't. 在这种情况下,语法之间的区别在于,在一种情况下,getter / setter被调用,而在另一种情况下,它们不会。 Correct? 正确?

I think it would be best to use Name rather than this.name. 我认为最好使用Name而不是this.name。 This way, only the getter/setter have access to the "unprotected" variable, and you can confirm any invariants about this value looking only at the getter and setter rather than at the whole class. 这样,只有getter / setter可以访问“unprotected”变量,并且您可以确认关于此值的任何不变量, 查看getter和setter而不是整个类。

I agree with the others; 我同意其他人; you generally want to use the property. 你通常想要使用该属性。 The reason for this is that you will get the logic that comes with it. 这样做的原因是你将获得随之而来的逻辑。 In WPF, for example, if you don't use the property and instead use the field PropertyChanged events won't be fired, which means that any controls bound to that property won't get updated. 例如,在WPF中,如果不使用该属性而是使用字段,则不会触发PropertyChanged事件,这意味着绑定到该属性的任何控件都不会更新。 Of course, you can't call the property within the property or you'll end up with a stack overflow. 当然,你不能在属性中调用属性,否则最终会出现堆栈溢出。

That said, there are times when you would want to avoid that logic entirely, and once in a while variable initialization falls under that. 这就是说, 有些时候你想完全避免这种逻辑,并在一段时间曾经变量初始化下跌倒。 In that case, you want to use the field. 在这种情况下,您要使用该字段。

My personal opinion is to preferably use the property unless that results in the incorrect behaviour. 我个人的意见是优先使用该属性,除非这会导致不正确的行为。 What it comes down to is that using the property indicates a commitment to the semantics of your class and the design of your API. 它归结为使用属性表示对您的类的语义和API的设计的承诺。

Obviously sometimes there are going to be exceptions to this rule... sometimes the 'property' means something distinct to the value of the backing field (in your example, the property raises an event). 显然,有时会出现这个规则的例外情况......有时候,“属性”意味着与支持字段的值不同(在您的示例中,属性会引发事件)。 If the internal use explicitly needs to avoid the semantics of the property (you don't want the event to fire), then the backing field is the correct 'second choice'. 如果内部使用明确需要避免属性的语义(您不希望事件触发),那么支持字段是正确的“第二选择”。

On an unrelated note, for better or for worse, the Microsoft StyleCop application specifically prefers the convention of accessing private fields with the 'this' prefix to differentiate access of local variables and class fields (rather than prefixing such as ' _ ' or ' m_ ' or variants thereof... which ironically are the convention used in legacy .NET framework code). 在一个不相关的注释中,无论好坏,Microsoft StyleCop应用程序特别喜欢使用'this'前缀访问私有字段的约定,以区分对局部变量和类字段的访问(而不是前缀如' _ '或' m_ '或其变体......具有讽刺意味的是传统.NET框架代码中使用的约定)。

Accessing the field within the property could potentially lead to an overflow if you're not careful. 如果您不小心,访问该属性中的字段可能会导致溢出。 I always access the property to avoid those potential situations. 我总是访问该物业以避免这些潜在的情况。

In the following setter, I can access property backing field directly or through the getter? 在下面的setter中,我可以直接或通过getter访问属性支持字段? Is there a scenario when one would be preferred over the other? 是否存在一个比另一个更受欢迎的情况?

only use it when there is a conflict with other variables in scope 仅在与范围中的其他变量发生冲突时使用它

There is a related question - how do you initialize properties in the c-tor? 有一个相关的问题 - 如何在c-tor中初始化属性?

If you have a property, use the property 如果您有房产,请使用该房产

I you don't want to raise the PropertyChanged event, access the field instead of the property. 我不想提出PropertyChanged事件,而是访问字段而不是属性。 However, in the constructor, you don't really care about raising that event, since you know for sure that no one has subscribed to the event yet... 但是,在构造函数中,您并不真正关心提升该事件,因为您确定没有人订阅该事件...

My recommendation is that if you have access to the field and the field does not require special logic. 我的建议是,如果您有权访问该字段,并且该字段不需要特殊逻辑。 An example: 一个例子:

private int width;
public int Width
{
    get 
    {
        return width;
    }
    set
    {
        if (value < 0)
            throw new InvalidArgumentException("Mass cannot be below 0");
        width = value;
    }
}

In this case you would NOT want to access the field, because you (probably) cannot guarantee that the value you are setting is above 0. However, if you have a property like: 在这种情况下,您不希望访问该字段,因为您(可能)无法保证您设置的值大于0.但是,如果您有以下属性:

public int Height { get; set; }

then it would probably be a good idea to access the field when possible. 那么在可能的情况下访问该字段可能是个好主意。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 插入数值的正确方法是什么 - What is the proper way to insert a numeric value 处理文件下载WebAPI拒绝访问的正确方法是什么 - What is the proper way to handle access denied on file download WebAPI 在Winform中访问用户控件的控件属性的正确方法是什么? - What is the proper way to access Controls properties of User Controls in Winform? 从单个嵌套的XElement中检索值的正确方法是什么? - What is the proper way to retrieve a value from a single, nested, XElement? 从语言文件绑定动态值的正确方法是什么? - What is the proper way to bind a dynamic value from a language file? 将字典值设置为 null 的引用类型的正确方法是什么? - What is the proper way to set a dictionary value which is a reference type to null? 锁定线程的正确方法是什么? - what is a proper way to lock threads? 等待连接的正确方法是什么? - What is the proper way to wait for connections? 在ASP.net的数据访问层中创建实体的正确方法是什么? - What is the proper way to create entities in data access layer in ASP.net? 在没有无限浮动值的情况下将百分比值从平面文件保存到数据库表的正确方法是什么? - What's the proper way to save percentage value from flat file to database table without infinite floating values?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM