Accessing private fields through properties…


(Writers note: I apologize for this C#-related post. I’ll return to posting trivial and useless information, reviews, and links soon)


A post on one of our internal groups came up asking whether a class’s implementation should use properties on that class, or whether it should restricted to fields. There was a bit of discussion, with some replying “sure”, and others saying that you should always use properties.


Here’s my take on it. The discussion is about a class that implements lazy loading of a bitmap property named “Bmp”.


<soapbox>

 

If you use properties for everything, you’re complicating the life of the code maintainer considerably. Instead of being able to trust that “bmp” has behavior that I understand (ie it’s a field), I have to go look at the definition of Bmp to see what’s going on.

 

In my book, that’s an example of premature generalization – you’re using a property *in case* you want to change things later. Premature generalization, like premature optimization, is something to be avoided. Or, as the agile guys would say, “You ain’t gonna need it” – you’re wasting time and bloating your class.

 

An exception to this is if you think you are going to version the class and client separately (ie you’re building a reusable library), and you wouldn’t be able to add in a property later.

 

If you use properties from inside your class when convenient – such as a lazy load of an bitmap – you’re still making things tougher on the maintainer – the difference between bitmap and Bitmap is pretty subtle, especially if you don’t have a naming convention for fields.

 

If you’re in that situation, I think it’s a far better solution to pull the lazy-loading code out of property and create a function named “GetBitmap()”, and use that function from inside the property and in other cases where you need the bitmap in your class. It’s more readable.

 

</soapbox>

Comments (10)

  1. Haacked says:

    What is this crap? I subscribed to your blog when you were a PM on the C# team, but when your blog changed towards trivial and useless information as well as excrutiating detail on your bike rides, I thought, "Now THIS is a blog worth reading. Eric has finally brought his A game!"

    But then you soil it by returning this insightful comment on "Premature Generalization" in C#. What do you expect to accomplish with this extremely helpful and useful post? Ewww.

  2. tzagotta says:

    I’m finding more and more that I am using properties to set initial values in constructors (either from constructor parameters or otherwise). The reason I am doing this is that I have side-effect code in the set accessor that I want to run when the value is assigned in the constructor. So I would say these sorts of cases would be best handled by having properties.

    I’m not sure why using properties would make life more difficult for a maintenance programmer. If you consider the possibility that in some cases you might want to use properties, and other cases, you might want to directly access fields, then when programming or maintaining a class, you have to think about whether to directly use the field or accessor each time. Maybe always using an accessor is easier in that case? What do you think?

    Also, with the awesome refactoring tools built into VS2005, encapsulating a field into a property is such a painless operation, that I can’t really see the practical value of always doing that up-front, except for cases like the one I described above.

  3. ericgu says:

    Haacked,

    You had me going there…

  4. ericgu says:

    Tzagotta,

    Perhaps I can explain a bit more clearly.

    When you’re doing maintenance, you spend a fair amount of time reading through code, trying to discover or (if it’s your own code) remember how something works. In doing so, you need to keep a lot of possibilities in mind – does it do x? does it do y?

    To the extent that you can constrain the things that you need to learn to understand a class, you make it easier for that class to understand.

    That’s the argument, though you don’t have to agree with it.

  5. RichB says:

    Deja-vu?

    I’m sure I’ve read a blog post from you 18 months ago which talked about using public fields rather than go to the hassle of creating properties with private storage.

  6. Darren Oakey says:

    I have a dislike for unexpected side-effects – so have a personal rule that any object which can be changed post-creation must also raise an event to say that that change has occurred – the corollory being – don’t create objects that are changed post-creation!

    But, for brevity and maintainability I’ve started using public fields instead of properties – the magic is the readonly field:

    public class Employee

    public readonly string FirstName;

    public readonly string LastName;

    public readonly Date Birthdate;

    public Employee( string name, string lastName, date birthdate)

    {

    Ensure.NotMissing( "firstName", firstName );

    Ensure.NotMissing( "lastName", lastName );

    Ensure.NotMissing( "birthdate", birthdate );

    FirstName = firstName;

    LastName = lastName;

    Birthdate = birthdate

    }

    }

    Not too much can go wrong with that – and I find it very quick to make and easy to read.

  7. barrkel says:

    The biggest elephant you folks are missing is binary compatibility. If you have a library that exposes something as a field, you can’t change that later to be a property.

    If there’s any chance that an already deployed version of the library exists in the wild along with clients that reference the field, changing it to a property is going to break those clients, especially if the library is in the GAC (which can still be desirable, for updating reasons).

  8. robburke says:

    I’d agree with the post and add that, in the event that a subsequent refactor from a Field to a Property is necessary, it’s highly unlikely to introduce breaking changes, unless you’re doing reflection tricks and iterating over Fields or something like that. So I tend to err on the side of not making everything a Property if the getters and setters are trivial and the thing is public to begin with.

    That being said… there are times I wish I could make public Fields behave more like public Properties. I wish I could easily ask the PropertyGrid to display my Fields as Properties, for instance…

  9. robburke says:

    barrkel – oops… you’re right of course. If it’s in the wild you’re out of luck.

  10. ericgu says:

    Barrkel,

    I did say that there’s an exception if you’re building a library that you need to version separately. I think both of those are important – there are many libraries that always ship as a unit with their clients and/or for which a recompile is not an issue.

    Eric