Click here to Skip to main content
15,885,546 members
Articles / Programming Languages / C#
Article

Self-Implemented Properties versus Public Fields

Rate me:
Please Sign up or sign in to vote.
3.92/5 (9 votes)
14 Jul 2008CPOL8 min read 43.7K   19   20
A single match between Properties and Fields and their implementations.

Introduction

In this article, I will discuss the use of Properties versus Fields. The new inclusion of Automatically Implemented Properties in the standard C# 3.0, often referred as Self-Implemented Properties, has caused developers to decide between properties and fields once again.

Background

The modern Object Oriented languages include the concept of fields and properties, both of which are extensions of the original idea of Objects. Since UML only defines attributes (not to be mistaken with the .NET feature), deciding between using a field or a property is sometimes done in design and sometimes is up to the developer.

What is a Field?

According to the ECMA-335 standard, a field is “a member that designates a typed memory location that stores some data in a program”. The same document is not very clear in defining the concept of a member, as it says “Member: Any of the fields, array elements, methods, properties, and events of a type”. All that matters to us is that a field, as any other variable, is a space in memory which stores a value, but a field exists in the class scope and maybe static or not; this is the great potential of the field when compared to a local variable.

A field allows us to maintain data across method calls or even across class instances (when it is static). We may also use access modifiers, such as public or protected, which allows us to access the data from outside the class.

If we compare a Field with a Local Variable, the Field is less secure and slower than the Local Variable, every time we may use a Local Variable instead of a Field, it is preferable to do it.

What is a Property?

According to the ECMA-335 standard (again), a property is “A member that defines a named value and the methods that access that value. A property definition defines the accessing contracts on that value. Hence, the property definition specifies which accessing methods exist and their respective method contracts.”

The developer may tent to think about properties as data, but actually, it is a method structure (like the event). If we examine the typical implementation of a property in IL, it looks like this:

MSIL
.method public hidebysig specialname instance int32
        get_Prop() cil managed
{
  //...
}
     
.method public hidebysig specialname instance void
        set_Prop(int32 'value') cil managed
{
  //...
}  
 
.property
instance int32 Prop()
{
  .get instance int32 Namespace.Class::get_Prop()
  .set instance void Namespace.Class::set_Prop(int32)
}

The example above shows a property named Prop of type int declared in the class Namespace.Class. As we can see, it is actually the junction of two methods, which intends to read and write the stored data. This method’s body is what we write inside the get {} and set {} for the property.

Form C# and any other .NET compliant languages, we can access the property as a unit, but in IL, any access to the property translates to a virtual call to the corresponding method.

Curiosity

Try writing a method with the same name as thef one used by a property and the same signature. For the Prop property shown above, for example, it could be:

C#
public int get_Prop() { } 

We will receive a compiler error, more formally the CS0082, that says:

"Type Application.Class already reserves a member 
   called get_Prop with the same parameter types"

Good and Bad Practice

It is widely recommended to use properties to encapsulate fields. For example, if we desire to access a value as read-only from outside a class, we may declare a read-only property, which encapsulates a private field, then we use that field to write the property value from inside the class. In C#, we may accomplish this as shown below:

C#
private int field;
public int Prop
{
    get { return field; }
}

Also, keep in mind the possibility of writing calculated properties; may be good to cache this kind of properties. For example, in this case:

C#
private double value;
public int Sqrt
{
    get
    {
        return Math.Sqrt(value);
    }
}

We could write:

C#
private double value;
private double value_sqrt;
public int Sqrt
{
    get 
    {
        return value_Sqrt;
    }
}

In addition, we will need to update the value of value_sqrt every time we change the value of the value field:

C#
value_sqrt = Math.Sqrt(value); //Somewhere is needed 

This reduces latency when reading the property, but since this is only an optimization, it is recommendable to keep the first form of the property since it will reduce code complexity and development time, and also will be easiest to read and maintain because the logic of the property will be spread through all the class in the second form.

There is also another kind of calculated properties, which refer to those that are non-static, non-constant, and are independent from the rest of the fields in the object. For example:

C#
public int RareValue
{
    get
    {
        return new Random().Next();
    }
}

It is encouraged to convert these kind of properties to methods, since they do not reflect the actual state of the object, with the only exception of using it to implement an Interface; if that is the case we may consider giving a revision to that Interface.

Properties versus Fields Scenario

As long as we do not need to define any logic in a property and we do not need to define any access modifiers for the property, it falls in the scenario of a property vs. field match. In the times of C# 2.0, the code complexity was a strong argument against the use of properties in this situation, but with Self-Implemented Properties in scene from C# 3.0, this is no longer true.

Self-Implemented Properties

To get in deep in this match, we first need to understand the functionality of self-implemented properties. The first thing to say is that it is really shorter; it allows us to write a property like this:

C#
public int Prop { get; set; } 

At first time for a C# 2.0 developer, it may look like an empty property or even an abstract definition of it, but this actually causes an error in any C# 2.0 scenario.

In a class, we must write the body for get and set, like this:

C#
public int Prop { get{} set{} }  

This will drive us to an odd property with no code at all. If we take the same example but replacing the type of the property with the reference type, we will receive a CS0161 compiler error: “not all code paths return a value”.

Another option is to set it as abstract like this:

C#
public abstract int Prop { get; set; }

In this case, an inheritor must implement the property and we must declare the class as abstract too.

In an interface, the use of the public keyword is not only redundant but also disallowed; the solution could be to write:

C#
int Prop { get; set; } 

This will drive us to a common property interface member.

In C# 3.0, the compiler generates the code for the methods of the property behind the scenes; this code reads and writes an anonymous member. The member of a self-implemented property is not accessible directly at design time, but we can reach it by Reflection. Actually, VS2008 will set their names like this:

‘<PropertyName>k__BackingField’

For example, for the property Prop, it could be:

‘<Prop>k__BackingField’

Round 1: Code Breaking

As we said before, the access to a property value is actually a virtual call, which is far form accessing a field. This will cause compatibly problems if we change a public field to a property from release to release. At this point, we may argue that the field access is faster than the virtual call. Even while this is true, it is only relevant in a real-time application, because in terms of functionality, there is not a difference, except in the mentioned situation.

In the other hand, the property will give us flexibility, considering the possibility of changing the logic of the property to include validation or to raise an event. If the life cycle model suggests keeping in mind this kind of modifications, the property is the obvious answer. If we need to expose the member outside of the system boundary, the use of a property instead of a field will reduce the maintenance costs.

In addition, as any experienced .NET developer knows, an Interface cannot define fields; this is because a field implicates reserving memory space, and to encourage this to the implementers will result in a polymorphism loss. This is an obvious advantage of properties, but of course, this is only in the case in which we decide to implement the interface and it requires the property. Once more, the property is prevention in case we will need to change the code without breaking any client code.

At the end of the first round, the score goes one for property and zero for field; it looks like we have a winner.

Round 2: Attributes, the Revenge

Self-implemented properties are not perfect, and one of the defects it has with it, is also its advantage, this is the lack of field declaration. Since we cannot access the declaration of the implicit anonymous field, we cannot decorate it with attributes. For example, if we need to define the value of the property as [NonSerialized], which causes the serialization system to ignore the field, we will need to use a classical property or a public field.

A more decisive case is the emulation of C++ union types (a data structure that allows reading or writing the same memory space in one or more ways defined like structs) in C#, with the following attribute:

C#
System.Runtime.InteropServices.FieldOffsetAttribute  

A full example of this technique is the following:

C#
using System; 
using System.Runtime.InteropServices;
 
namespace
Application
{
    [StructLayout(LayoutKind.Explicit)]
    class Union
    {
        [FieldOffset(0)]
        public Int32 LoWord;
        [FieldOffset(4)]
        public Int32 HiWord;
        [FieldOffset(0)]
        public Int64 Word;
    } 
  
    class Program
    { 
        static void Main()
        { 
            var A = new Union(){ Word = 1234567890123456789 };
            Console.WriteLine(A.Word);
            Console.WriteLine(A.HiWord);
            Console.WriteLine(A.LoWord);
            Console.WriteLine(A.LoWord + (long)((long)A.HiWord << 32));
            Console.ReadKey();
        }
    }
}

The output of the previous code is this:

1234567890123456789
287445236
2112454933
1234567890123456789

This is actually the simplest and fastest logic for the classical HiWord and LoWord Algorithms in C# 2.0 and any newer release of the language, and a great hit in favor of Fields for those who thought is was here only for compatibility reasons.

Lastly, at the end of the second round, the score is one for property and one for field; we have a draw, may be we will continue this match in the future...

Conclusion

After a heavy battle between fields and properties, we can conclude that properties are more flexible and recommendable from a design point of view, but when it comes to unleashing the language power (maybe only the freelance developers are up to this, at their own risk, of course), may be with attributes or in terms of speed, the fields come in handy.

Remember that even if we could use private self-implementing properties to write a fully functional application without even writing a single field, they will be there in the shadows of IL doing the game of curtains for our show. Both properties and fields have their own place in this modern language, and in other .NET compliant ones.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Systems Engineer
Colombia Colombia
My name is Alfonso Ramos, I'm a Independend Software Developer Certified by Microsoft, In my interests are the video games, making them and of course playing them ^_^.

Comments and Discussions

 
NewsI'm working on it! Pin
Theraot22-Jul-08 19:48
Theraot22-Jul-08 19:48 
GeneralRe: I'm working on it! Pin
Theraot1-Oct-08 23:13
Theraot1-Oct-08 23:13 
I know, I know, I said that, I lost my work...

Well anyway, this will be obsolete soon; I've been sending feedback to Microsoft. And you'll see explicit fields to lose the match.
GeneralConstants Pin
TobiasP22-Jul-08 5:35
TobiasP22-Jul-08 5:35 
GeneralOne hint Pin
Przemyslaw Celej21-Jul-08 23:13
Przemyslaw Celej21-Jul-08 23:13 
QuestionMissed the point? Pin
Wouter van Vugt15-Jul-08 0:16
Wouter van Vugt15-Jul-08 0:16 
AnswerRe: Missed the point? [modified] Pin
Theraot15-Jul-08 3:03
Theraot15-Jul-08 3:03 
GeneralRe: Missed the point? Pin
Wouter van Vugt15-Jul-08 3:48
Wouter van Vugt15-Jul-08 3:48 
GeneralRe: Missed the point? Pin
Theraot15-Jul-08 13:13
Theraot15-Jul-08 13:13 
GeneralRe: Missed the point? Pin
Wouter van Vugt15-Jul-08 21:56
Wouter van Vugt15-Jul-08 21:56 
GeneralRe: Missed the point? Pin
Theraot16-Jul-08 14:16
Theraot16-Jul-08 14:16 
GeneralThanks for the Union class Pin
Sharpoverride14-Jul-08 22:16
Sharpoverride14-Jul-08 22:16 
GeneralRe: Thanks for the Union class Pin
Theraot15-Jul-08 3:11
Theraot15-Jul-08 3:11 
GeneralRe: Thanks for the Union class Pin
Sharpoverride15-Jul-08 7:13
Sharpoverride15-Jul-08 7:13 
GeneralGood article Pin
Marc Clifton14-Jul-08 9:57
mvaMarc Clifton14-Jul-08 9:57 
GeneralREMOTE DESKTOP ACTIVE X CONTROL C# Pin
dementia12314-Jul-08 3:38
dementia12314-Jul-08 3:38 
GeneralRe: REMOTE DESKTOP ACTIVE X CONTROL C# Pin
Theraot14-Jul-08 4:27
Theraot14-Jul-08 4:27 
GeneralRe: REMOTE DESKTOP ACTIVE X CONTROL C# Pin
Theraot14-Jul-08 4:44
Theraot14-Jul-08 4:44 
GeneralRe: REMOTE DESKTOP ACTIVE X CONTROL C# Pin
domain_controller9-Aug-08 6:13
domain_controller9-Aug-08 6:13 
GeneralRe: REMOTE DESKTOP ACTIVE X CONTROL C# Pin
domain_controller9-Aug-08 6:21
domain_controller9-Aug-08 6:21 
GeneralRe: REMOTE DESKTOP ACTIVE X CONTROL C# Pin
Theraot10-Aug-08 10:48
Theraot10-Aug-08 10:48 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.