Friday, February 02, 2007

Public fields and properties are not compatible

If your class wants to expose some data, you have two possibilities:

  1. Use a public field
    public class Person { public string Name; }
  2. Use a public property that is backed by a private field
    public class Person { private string name; public string Name { get { return name; } set { name = value; } } }

The general advise is that you should not have any public fields, thus you should always use properties. However some people suggest that you can start out with a public field and that you can easily change it into a property when the need arises.

But this is not true for two reasons:

  1. A public field and a property are binary incompatible. When you change your public field into a property you will have to recompile all the clients of your class.
  2. A public field and a propery are also incompatible at source-code level. A public field can be passed as a ref- or out-parameter while a property cannot. So when you change your public field into a property, you may have to actually change the client code which may not be a trivial task.

So my advise: unless you have *very* strict performance considerations always use properties.

Regarding performance, keep in mind that a simple propery that is not marked as virtual (or that is part of a sealed class) will likely be inlined by the compiler so there shouldn't be any performance impact at all (in release-builds).



Elmar Juergens said...

You are certainly right. But shoudln't I avoid using public fields as ref or out parameters anyway?

This would vertainly have to be checked automatically. But using the Microsoft.Cci, shoudln't it be rather simple to implement a static code analyzer that warns me if I use a public field as a ref or out parameter?

Would you accept that as a sort of compromise?

Kristof said...

Passing a parameter as ref or out is indeed often misused (especially when its a reference type). I believe that only local variables should be passed as ref or out.

FxCop is an example of such a static code analyzer that has rules for this, see here.

noopman said...

What about the code design angle?

Here's my take on the matter



Kirill Osenkov said...

Kristof, good point about ref and out parameters!

Anonymous said...

So here is a question, when you need to read the values do you use the Property or internal field, especially if you are reading for a call internal for the class?

Anonymous said...

Fields and properties are also different implementations in the eyes of reflection. Refactoring a field as a property and vice-versa also requires you to refactor any reflection-related reads and writes of that property. Since reflection-implemented reads/writes are performed in a non-typesafe manner, the compiler won't catch it and you see the problem at run-time.

You also don't always have the ability to change the reflection-based code. (i.e. data-binding code in framework UI elements typically want you to specify a property or properties on the object used as it's "data-row")