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

时间:2009-06-04 22:15:26

标签: c#

在下面的setter中,我可以直接或通过getter访问属性支持字段。是否存在一个人比另一个更受欢迎的情景?

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);
            // ?
        }
    }

有一个相关的问题。你会如何在c-tor中初始化属性?

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

我使用this.name,因为在构造时实例可能处于无效/不稳定/未定义状态,因此Name-setter验证可能会错误地失败。还有其他意见吗?

9 个答案:

答案 0 :(得分:3)

我会说“Name = name”更正确,因为如果你要将“name”属性声明为virtual,那么有人可能会覆盖你的属性行为,但你的构造函数仍会绕过它们的逻辑。 /击>

此外,属性可以封装行为,例如提升更改事件,您不应绕过这些行为。在构造对象之前,任何用户都无法为事件添加处理程序。因此,如果在具有外部事件的构造函数中进行设置,则不会引发该设置。

修改

请参阅下面的评论,了解为什么虚拟是一个糟糕的例子。

答案 1 :(得分:2)

我个人解决这个问题的方法是

  

只有在使用此限定符时才会导致不正确的行为或编译错误。

我更喜欢在这个限定符的绝对值中使我的代码可读。如果没有这个限定符它是不可读的,我会努力将代码更改为可读。

答案 2 :(得分:2)

在这种情况下,语法之间的区别在于,在一种情况下,getter / setter被调用,而在另一种情况下,它们不会。正确的吗?

我认为最好使用Name而不是this.name。这样,只有getter / setter可以访问“不受保护”的变量,并且你可以确认任何关于这个值的不变量,只能在getter和setter而不是整个类中查找

答案 3 :(得分:1)

我同意其他人的意见;你通常想要使用该属性。这样做的原因是你将获得随之而来的逻辑。例如,在WPF中,如果不使用该属性而是使用字段,则不会触发PropertyChanged事件,这意味着绑定到该属性的任何控件都不会更新。当然,你不能在属性中调用属性,否则你最终会出现堆栈溢出。

也就是说,当你想要完全避免这种逻辑时,次,并且偶尔变量初始化就属于这种情况。在这种情况下,您想要使用该字段。

答案 4 :(得分:1)

我个人的意见是优先使用该属性,除非这导致不正确的行为。它归结为使用属性表明了对类的语义和API设计的承诺。

显然有时会出现这个规则的例外情况......有时候,“属性”意味着与支持字段的值不同(在您的示例中,属性会引发事件)。如果内部使用明确需要避免属性的语义(您不希望触发事件),那么支持字段是正确的“第二选择”。

在一个不相关的说明中,无论好坏,Microsoft StyleCop应用程序特别喜欢使用'this'前缀访问私有字段的约定来区分对局部变量和类字段的访问(而不是前缀这样的作为'_'或'm_'或其变体......具有讽刺意味的是传统.NET框架代码中使用的约定。)

答案 5 :(得分:1)

如果您不小心,访问该属性中的字段可能会导致溢出。我总是访问该物业以避免这些潜在的情况。

答案 6 :(得分:0)

  

在下面的setter中,我可以直接或通过getter访问属性支持字段?是否存在一个人比另一个更受欢迎的情景?

仅在与范围

中的其他变量发生冲突时使用它
  

有一个相关的问题 - 如何在c-tor中初始化属性?

如果您有房产,请使用房产

答案 7 :(得分:0)

我不想提出PropertyChanged事件,而是访问字段而不是属性。但是,在构造函数中,您并不真正关心提升该事件,因为您确定没有人订阅该事件...

答案 8 :(得分:0)

我的建议是,如果您有权访问该字段,并且该字段不需要特殊逻辑。一个例子:

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

在这种情况下,您不希望访问该字段,因为您(可能)无法保证您设置的值高于0。 但是,如果您有以下属性:

public int Height { get; set; }

然后在可能的情况下访问该字段可能是个好主意。