我应该通过属性setter还是不在C#中分配类字段

本文关键字:分配 字段 属性 setter 我应该 | 更新日期: 2023-09-27 18:26:50

正确的方法是什么?属性setter可能包含比实际赋值更多的代码。假设我有以下代码:

class Person
{
    private String name;
    public Person(String name)
    {
        this.name = Name
    }
    public String Name
    {
        get;
        set {
            if(String.Empty.Equals(value)) return;
            this.name = value;
        }
    }
}

由于我不是通过属性分配的,所以上面的代码是错误的吗?

我应该通过属性setter还是不在C#中分配类字段

  1. 除非有充分的理由,否则即使在同一个类中,也应该使用属性Name而不是字段name,以确保始终使用get/set方法中的逻辑
  2. 由于您显式指定了set实现,因此还必须显式指定get实现以供示例编译
  3. 在大多数情况下,您应该使用String.IsNullOrEmpty,而不是像String.Empty.Equals(value)代码这样的其他方法
  4. 房产的行为通常应该出人意料。运行person.Name = "";之后,您会期望Name属性为"",而不是以前的属性。如果设置null或空名称无效,则在传递此类值时应引发异常。

    class Person
    {
        private String name;
        public Person(String name)
        {
            this.Name = name;
        }
        public String Name
        {
            get {
                return this.name;
            }
            set {
                if(String.IsNullOrEmpty(value))
                    throw new ArgumentException("Name is required", "value");
                this.name = value;
            }
        }
    }
    

通常,您应该通过属性setter进行赋值,因为setter是用来维护类不变量的。绕过setter意味着在直接修改后备字段时必须手动维护这些不变量,这会使您暴露在错误中,并可能违反DRY原则。

您已经证明绕过setter会带来重要性能优势的特定情况下,可以忽略此规则。

属性的行为方式应该不足为奇。这意味着,如果我这样做:

someObject.SomeProperty = someValue;

然后,在这样做之后,以下情况应该为真(假设属性的类型允许比较),或者应该抛出异常:

someObject.SomeProperty == someValue;

例如,如果您不希望调用者将属性设置为null或空字符串,那么如果他们这样做了,您应该抛出一个ArgumentException

public String Name
{
    get 
    {
        return this.name; 
    }
    set 
    {
        if (string.IsNullOrEmpty(value))
            throw new ArgumentException("value");
        this.name = value;
    }
}

我不想看到这种东西:

myObject.Name = "Fred";
// ... Lots of code
myObject.Name = "";
string test = myObject.Name;
// Now test == "Fred" wtf?