Fun with C# Properties

Everyday sugar

C# loves us and wants us to be happy

C# gives us some really great syntactic sugar so we don’t have do all the manual things. Today we’re looking at properties. In older languages it’s common to just declare a public member and call it a day and if you want to hide the variable you encapsulate in getter and setter methods. C# is actually doing the same thing with properties but taking away some of the clutter for us. Let’s checkout a few scenarios.

public int someVariable;

This is great we can get and set the value directly and life is simple and easy. But sometimes we don’t want things touching the variable directly. So we’ll make it private and make some getters and setters like so.

private int someVariable;

public int getSomeVariable()

{

return someVariable;

} public void setSomeVariable(int value)

{

someVariable = value;

}

Great now we can trust that the internal variable is only going to get changed how we like. But that’s a lot of code. Especially if we have to do that for all our variables. Along comes C# with a little help.

private int someVariable;

public int SomeVariable

{

get { return someVariable; }

set { someVariable = value; }

}

Great what an improvement! We still need the private member and the get and set methods but the code has been compacted a bit. Much less typing and so easy to read. But if we have a bunch of these it’s still going to be the same code over and over again with just different variable names. So C# got rid of that for us too and gave us the auto-property.

public int SomeVariable { get; set; }

Amazing! Just as easy as a public member, but now we can change it in the future without breaking any calling code. Thanks C# you’re the best.

Further down the rabbit hole

Let’s take a look behind the scenes to see what makes this work. I made up a quick example of a class that has an auto-property, a normal property with a private member backing it, and getter and setter methods. If you scroll down to the IL you can see that the get and set on the property create normal methods called get_Bar and set_Bar. If you compare the methods getBar to get_Bar and setBar to set_Bar, you can see the exact same code is produced. The auto-property getters and setters are little different because it’s making up its own backing field but even then the end result is the same.

Just your everyday class in C#

class Herp

{

// Auto Property

public int Foo { get; set; } // Private member used for the Bar property

private int bar; // Property with backing field

public int Bar

{

get {return bar;}

set {bar = value;}

} // Just a normal method

public void setBar (int i)

{

bar = i;

} // Just a normal method

public int getBar ()

{

return bar;

}

}

Here be dragons

Herp.get_Foo:

IL_0000: ldarg.0

IL_0001: ldfld UserQuery+Herp.<Foo>k__BackingField

IL_0006: stloc.0

IL_0007: br.s IL_0009

IL_0009: ldloc.0

IL_000A: ret Herp.set_Foo:

IL_0000: ldarg.0

IL_0001: ldarg.1

IL_0002: stfld UserQuery+Herp.<Foo>k__BackingField

IL_0007: ret Herp.get_Bar:

IL_0000: nop

IL_0001: ldarg.0

IL_0002: ldfld UserQuery+Herp.bar

IL_0007: stloc.0 // CS$1$0000

IL_0008: br.s IL_000A

IL_000A: ldloc.0 // CS$1$0000

IL_000B: ret Herp.set_Bar:

IL_0000: nop

IL_0001: ldarg.0

IL_0002: ldarg.1

IL_0003: stfld UserQuery+Herp.bar

IL_0008: ret Herp.setBar:

IL_0000: nop

IL_0001: ldarg.0

IL_0002: ldarg.1

IL_0003: stfld UserQuery+Herp.bar

IL_0008: ret Herp.getBar:

IL_0000: nop

IL_0001: ldarg.0

IL_0002: ldfld UserQuery+Herp.bar

IL_0007: stloc.0 // CS$1$0000

IL_0008: br.s IL_000A

IL_000A: ldloc.0 // CS$1$0000

IL_000B: ret Herp..ctor:

IL_0000: ldarg.0

IL_0001: call System.Object..ctor

IL_0006: ret

Fun Fact

If you have a property Bar {get;set;} and try to create a method called get_Bar or set_Bar it will fail because the method already exists.