Last week, I had a discussion with some friends about the new features in C# programming language. It is kind of interesting that for most of the new features, I always found myself start with some sort of reluctance and then gradually accept it and finally find myself couldn’t write code without it. When I started learning C# a few years ago, I didn’t even like properties (I was a big fun of java). I didn’t understand that if they are just getters and setters, why we were bothered to have properties and let the complier hiding the truth? But now, I can’t imagine how I can write program without them. In my discussion, I told my friends that now I so much prefer the syntax of counter.Count++ over counter.setCount(counter.getCount() + 1).
Today, I suddenly realised that have given a very bad example. It actually shows the opposite of my point.
Yes, we all agree that counter.setCount(counter.getCount() + 1) is very ugly syntax, as a programmer who only write beautiful code, we all unhappy with it. So, it will make us to think, how can we make it better, should the getter and setter exist at the first place, isn’t it a clear sign of breaking the Law of Demeter? Then we may come up with better solution like this:
public class MyFancyCounter
{
private int count;
public void Increase()
{
count++;
}
}
As for counter.Count++, we are so happy with the syntax, we are probably never going to think if we should expose Count as a property, even though it does exactly the same as counter.setCount(counter.getCount() + 1).
So, with properties, life is easy. And it is so easy, that we are going to expose every single field as a property. In C#3, it is made even easier by have this syntax:
public int Count { get; set; }
By the way, can anyone tell me is there any real difference between public int Count { get; set; } and public int Count;? To me, they are the same. But as we all know public fields are very bad and we all love the ease of the public fields, this feature is kind of making compromise so that we can have public fields without feeling guilty. I remember a couple of years ago when this feature was demonstrated in a meeting, people were so excited and cheering loudly. I didn’t understand why people love it so much, are we going to tell our boss that we can finish the next project on time because we don’t have to type in all the properties?
Encouraging unnecessary exposure of private fields is not the only problem. A property gives impression of that it a simple field access, but in fact it is a method and it can do arbitrarily anything. Sometimes a property can cause great confusion when it is not supposed to be a property. Here is a real world story I can share. When I started working on a system a year ago, I found some services were suffering badly from memory leak. After running the service for a couple of hours, its memory usage shot up from 20M to 600M. With some help from Windbg/SOS, I found that all the WCF Channel objects were never got freed up. When I looked the code I find this pattern is used throughout the whole system:
ISecurityService service = serviceManager.SecurityService;
User[] users = service.GetUsers();
When I jumped into serviceManager.SecurityService, the code was something like this:
public ISecurityService SecurityService
{
get { return _securityFactory.CreateChannel(); }
}
The SecurityService property actually created a new instance of Channel every time it gets called! And as the factory object maintains the reference to all the channel objects it created, if you don’t explicitly dispose a channel object, it will never be garbage collected. So the correct way of using SecurityService is this:
using (ISecurityService service = serviceManager.SecurityService)
{
User[] users = service.GetUsers();
}
But do you feel it just looks wired? Yes, because you feel you are disposing a private field of serviceManager which might be used by someone else. I guess that is why everyone was deceived by the serviceManager.SecurityService property. So in this case, changing SecurityService property to method will make things much clearer. Like following:
public ISecurityService CreateSecurityService()
{
return _securityFactory.CreateChannel();
}
and
using (ISecurityService service = serviceManager.CreateSecurityService ())
{
User[] users = service.GetUsers();
}
Despite of the title of this post, I have no intention to challenge the existence of properties in C#. I love to use properties myself, even this one: public int Count { get; set; }
What I really want to say is sometimes to use a property is not a simple choice. When you enjoy the ease of the syntax you should ask some questions:
- Do I really need to expose a field as a property?
- Is it semantically very different from a field access?
- Will the operation be much complicated than a field access?
- Will calling the getter have a side effect?
- Will the getter return different result every time it is called?