This is my third post on MSIL – Microsoft Intermediate Language – which is generated by the Visual C# compiler once the code is compiled. In this post I’ll take a look at the intermediate language generated for the properties of a class.
Here are my last two posts on MSIL.
The lies of the C# compiler : It explores the MSIL equivalent of the C# accessors like protected, internal etc.
Exploring MSIL – Static and Instance Methods : It explores the difference in the MSIL generated for static and instance methods.
I’ll create create a class BankAccount and add the properties CustomerName and Balance. CustomerName gives both read and write access while Balance is only read-only. The class members have been kept on minimum to focus on the MSIL generated for a property. Here is the code.
public class BankAccount
{
private string customerName;
private float balance;
public BankAccount(string name, float bal)
{
this.customerName = name;
this.balance = bal;
}
public string CustomerName
{
get { return customerName; }
set { customerName = value; } // both read and write access
}
public float Balance
{
get { return balance; } // read-only
}
}
And here is the intermediate language that is generated once the project is compiled.
The following points are worth observing.
1. Apart from generating the properties, the get_xxx and set_xxx methods have also been generated.
2. The get_xxx method is generated for the get accessor and the set_xxx method is generated for the set acessors in the property.
3. The get_xxx method returns a value of the same type as the field that is encapsulated by the property. For example, get_Balance() returns a float that is of the same type as the field balance.
4. The set_xxx method takes an argument and returns void. Again the type of the argument is same as the field that is encapsulated by the property.
Now let us have a closer look at the intermediate language generated for the property – CustomerName and it’s get and set accessors.
.property instance string CustomerName()
{
.get instance string BankAccount::get_CustomerName()
.set instance void BankAccount::set_CustomerName(string)
} // end of property BankAccount::CustomerName
The property, CustomerName, is an instance one and the field that it encapsulates is a string. It provides both read and write access. In case this property had encapsulated a static field, the word instance would had been missing and NOT replaced by static.
.method public hidebysig specialname instance string
get_CustomerName() cil managed
{
// Code size 12 (0xc)
.maxstack 1
.locals init ([0] string CS$1$0000)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldfld string BankAccount::customerName
IL_0007: stloc.0
IL_0008: br.s IL_000a
IL_000a: ldloc.0
IL_000b: ret
} // end of method BankAccount::get_CustomerName
The get acessor of the property is actually an instance method that returns a string. I’ll explain the IL instructions in another post.
.method public hidebysig specialname instance void
set_CustomerName(string ‘value’) cil managed
{
// Code size 9 (0×9)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldarg.1
IL_0003: stfld string BankAccount::customerName
IL_0008: ret
} // end of method BankAccount::set_CustomerName
The set acessor of the property is also an instance method that takes a string argument – value.
I believe this post gives a little more insight into the MSIL generated for the properties.



This is the most useful article that I found after searching for 10 days.
Summary: To create a delegate to the accessors of a method, the process is exactly similar to that for methods, except that the name needs to be prefixed by get_ or set_.
Key words: Accessor Delegate C# get set