Properties vs. Methods
Not so much a code as what you might call 'guidelines'

Recently, one of the readers of Effective C# asked me some questions about Properties vs. Get and Set methods.  It turned into a rather interesting conversation, so I'm posting it all here:

The original Question:

I'm writing because of a discussion we've been having about the first item in your book. As you know, that item says to "Always use properties instead of accessible data members."

Our main issue is that the book doesn't explain the value of properties over the traditional set/get method approach. In fact, some of the folks on the team are arguing that properties are just syntactic sugar that have more negatives than positives. One example given is that if a property has both set and get implemented then the property could accidentally be assigned when the intention was comparison
        obj.serverDown = false
versus the desired
        obj.serverDown == false
Whereas, with the traditional set/get method, the above bug isn't possible
        ! obj.IsServerDown()

I'm curious what your opinion/rationale is on the topic? Also, do you know of any other
references (online or in print) that discuss this issue?

My first answer:

There are a few reasons why I believe Properties are beneficial vs. the traditional get and set methods used in earlier OO languages (such as C++). 

Consider SOA and a document centric API:

Properties are naturally serialized using the XML serializer. Therefore, a list of employees defined using properties becomes a simple XML document for wire transfer. (I’m assuming read/write properties for Name, Salary, etc).  You can’t easily use the XML serialize for a similar type implement using get / set methods. This is a necessity to build SOA applications where the client will request a document from the server.  The natural document is the set of public properties for a data type. (The same argument can be made for the client code, where a command document is a type with a set of public properties).

Databinding:

This one may be cheating, because one could argue that MS could implement databinding using get / set methods.  But they didn’t, so properties are the clear winner here. And, in fact, if MS did use a get / set metaphor, it would be similar to Java beans, where get_ and set_ denoted a property.  Personally, I dislike the idea that a methods name can give it magical behavior.

Clarity:

Despite the text in the article you reference below, I think there is merit to the property syntax, when used correctly.  It clearly shows that a type contains certain data elements (at least logically, even if not physically).  Point.X looks cleaner to me than Point.get_X(), or Point.set_X(256).  The syntax of the language expresses the design intent more clearly.  That’s certainly subjective, but that’s my opinion.

To address your concern below, there are two answers.  First, it’s much less likely to make the mistake of if (obj.ServerDown = false) because it can only be done with boolean types (not any arbitrary integral type as in C or C++). Secondly, the habit of putting the constant on the left side fixes that as well: if (false == obj.ServerDown).

On the question of hiding inefficiencies behind properties:

Let's consider this code:

public void Calc(int[] foo)
{
  Sum = 0;
  for (int i = 0; i < foo.Length; i++)
    Sum += foo[i];
}

It is indeed possible that the Length property (or the indexer) cause serious inefficiencies.  (Look at the code again, and imagine that Sum is a property with Get and Set accessors.) But, let's not get carried away. In most cases, the JIT compiler will inline simple properties, and there is no inefficiency at all. Of course, you may consider caching the temp variable anyway, and there may be some savings, if the setter has extensive validation.

Syntactically, you could hide anything inside a property's get or set methods.  You could even include database access to retrieve (or set) the value. But, just because it's syntactically correct doesn't mean you should do it.  I’d say it’s a bad practice to hide a database access behind a property for several reasons.  Would you ever make a database call to retrieve one scalar value?  (That’s what such a getter would look like.) Wouldn’t it be far more likely that you would design your application to pull some reasonable set of data from the database and have it locally available?  My point is that I wouldn’t believe GetCommission() makes a database call any more than a SalesPerson.Commission property. And, if the app really does use some form of lazy evaluation, you’re paying the performance hit regardless of the property or method syntax, so it really doesn’t matter.

So, if the argument is that properties are ‘hiding’ performance issues, I don’t think that’s often true.  Most developers would think getSomething() and setSomething() would contain the same code as a Something property. The JIT compiler knows a property is a get / set method pair and can perform the same optimizations as a get / set method pair. So, you really don’t lose anything.  In some sense, properties are syntactic sugar (there’s no new amazing functionality here), but the XML Document serialization and databinding are the two practical reasons to prefer them over get / set methods.  Your colleagues have found the one negative (= vs. ==), which has been around since the dawn of C, so we’ve probably got the habits to handle that one.

After that initial dialogue, the reader and I discussed some guidelines for deciding between properties and methods.  Because, there are performance pitfalls hiding behind properties and indexers, if misused.

Here's what we came up with:

  • Use a Property when all these are true:
    The getters should be simple and thus unlikely to throw exceptions.  Note that this implies no network (or database) access. Either might fail, and therefore would throw an exception.
  • They should not have dependencies on each other.  Note that this would include setting one property and having it affect another.  (For example, setting the FirstName property would affect a read-only FullName property that composed the first name + last name properties implies such a dependency )
  • They should be settable in any order
    The getter does not have an observable side effect Note this guideline doesn't preclude some forms of lazy evaluation in a property.
  • The method must always return immediately. (Note that this precludes a property that makes a database access call, web service call, or other similar operation).
  • Use a method if the member returns an array.
  • Repeated calls to the getter (without intervening code) should return the same value. 
  • Repeated calls to the setter (with the same value) should yield no difference from a single call.
  • The get should not return a reference to internal data structures (See item 23). A method could return a deep copy, and could avoid this issue.



Created: 9/4/2006 7:04:23 AM

Current Projects

I create content for .NET Core. My work appears in the .NET Core documentation site. I'm primarily responsible for the section that will help you learn C#.

All of these projects are Open Source (using the Creative Commons license for content, and the MIT license for code). If you would like to contribute, visit our GitHub Repository. Or, if you have questions, comments, or ideas for improvement, please create an issue for us.

I'm also the president of Humanitarian Toolbox. We build Open Source software that supports Humanitarian Disaster Relief efforts. We'd appreciate any help you can give to our projects. Look at our GitHub home page to see a list of our current projects. See what interests you, and dive in.

Or, if you have a group of volunteers, talk to us about hosting a codeathon event.