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).

Kristof.

6 comments:

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

Cheers,

/Magnus

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")