简体   繁体   中英

Should I assign class fields via property setter or not in C#?

What is the correct way of doing this? The property setter might contain more code than just the acctual assignment. Lets say I have the following code:

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

Is the above code wrong since I am not assign via the property?

  1. Unless you've got a good reason to do otherwise, you should use the property Name instead of the field name , even in the same class, to ensure that the logic in your get / set methods is always used.
  2. Since you explicitly specify a set implementation, you must also explicitly specify a get implementation for your example to compile.
  3. In most cases, you should use String.IsNullOrEmpty , not other approaches like your String.Empty.Equals(value) code.
  4. Properties should usually behave in unsurprising ways. After you run person.Name = ""; , you'd expect the Name property to be "" , not what it was before. If setting a null or empty name is not valid, you should throw an exception when you are passed such a value.

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

In general you should assign via the property setter because setters are there to maintain class invariants . Bypassing the setter means that you must manually maintain these invariants when directly modifying the backing field(s), exposing you to bugs and possibly violating the DRY principle.

In specific cases where you have already proven that bypassing the setter yields important performance benefits, feel free to disregard this rule.

Properties should behave in an unsurprising way. That means that if I do:

someObject.SomeProperty = someValue;

then after doing so, either the following should be true (assuming that the type of the property allows comparison), or an exception should have been thrown:

someObject.SomeProperty == someValue;

For your example, if you do not want the caller to set the property to a null or empty string then you should throw an ArgumentException if they do so:

public String Name
{
    get 
    {
        return this.name; 
    }

    set 
    {
        if (string.IsNullOrEmpty(value))
            throw new ArgumentException("value");

        this.name = value;
    }
}

I would not like to see this kind of thing:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM