Contents
- Introduction
- How does it work?
- var and details
- Auto-Implemented Properties
- += and -= in Events
- Limitations
- Related Articles
- History
- References
Source code and Demo
Introduction
The C# language of the .NET(MSDN), has many features such as var to declare variable, implement the properties automatically and many more which makes life of a programmer easier. On the other hand, this abstraction creates a bit of confusion such as how does it work, how .Net implemented those stuffs in behind the scene. In this article, I will try to find out few of those stuff for example, var, Auto-Implemented properties and += or -= syntax used in Events.
How does it work?
In the following discussion, we will see how does var, auto-implemented properties and += and -= of Events work
var and details
In C#, it is possible to declare variable in few ways, implicit type declaration using var keyword is one of those. For example, it is possible to use var totalSalary =0; instead of int totalSalary =0;. As MSDN article suggested var is strongly typed but compiler determined the types. To explore it a bit more, I created a small class,
namespace TestHarness
{
public class VarExplorer
{
public Book ExploreVar()
{
var myBook = new Book() { Name = "What is out there?" };
myBook.Name = "What is out there?";
return myBook;
}
}
public class Book
{
public string Name { get; set; }
}
}
The above class is not doing much rather initialising an instance of type Book which contains a method named ExplorerVar. This method has variable declared using var. In the design time or coding or while writing code in the IDE, hover the mouse just above the keyword var then the compiler will determine the types of variable myBook. Please have a look the image below,
Fig: var at design time
So it is clear that compiler determine the types at design time. Another question is what is happening at runtime? To test, I compiled the TestHarness project and grab the TestHarness.exe from the bin folder and drop into .Net Reflector program, using the help .Net Reflector the code I found out for ExploreVar method is as below,
public Book ExploreVar()
{
Book <>g__initLocal0 = new Book {
Name = "What is out there?"
};
Book myBook = <>g__initLocal0;
myBook.Name = "What is out there?";
return myBook;
}
The above code clearly shows that compiler replace var keyword with appropriate type while building project as exe. From the above discussion, it is clear how does var work in C#.
Auto-Implemented Properties
In C# class declaration is pretty easy we declare a class using following syntax,
public class Book
{
private string name;
public string Name
{
get {
return name;
}
set {
name = value;
}
}
}
It is really simple but from C# 3.0 it is more easier. We can declare Book class as below,
public class Book
{
public string Name { get; set; }
}
Now the question is what is the difference between that syntax used to declare a class. In reality there is nothing except compiler doing all the work for us. A Bit of background of class, the concept of the Encapsulation has been implemented in different way. First declaration of Book class, the encapsulation has done by introducing Properties which actually equivalent to Get and Set method. So it is not possible to directly access the private members of the class unless there is a Public Properties or Get/Set method.
Now for the second syntax of the Book declaration, compiler is doing all this encapsulation on behalf of a programmer. When decompile second version of Book using .Net Reflector, Compiler itself generates get and set methods for Name property and declare a variable name <Name>k__BackingField ( in here <Name> is actuall property name defined in Book class ),
So whole decompiled code for Name is as below,
private string <name>k__BackingField;
public void set_Name(string value)
{
this.<name>k__BackingField = value;
}
public string get_Name()
{
return this.<name>k__BackingField;
}
From the above discussion clear that how compiler handle auto implemented properties. A bit more investigation at runtime, I created following code snippet to test the auto implemented properties stuff at run time,
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
public class AutoImplementatedProperties
{
public IEnumerable<string> ExploreMembers(Person personObject)
{
return personObject.GetType().GetMembers().ToList<memberinfo>().Select(memberInfo => memberInfo.Name);
}
public IEnumerable<string> ExplorePrivateFields(Person personObject)
{
return personObject.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Select(fieldInfo => string.Format("{0,40}-->{1,20}", fieldInfo.Name, fieldInfo.GetValue(personObject).ToString()));
}
public Person CreateATestObject()
{
Person personObject = new Person()
{
Name = "M",
Profession = "Coding"
};
return personObject;
}
}
public class Person
{
public string Name { get; set; }
public string Profession { get; set; }
}
}
In the above class, ExploreMembers method will explore all the members of Person object and ExplorePrivateFields will explore all the private fields including their value of Person object. If we run the ExplorePrivateFields method then we can see it will display,
Fig: Auto-implemented properties test result.
Above output and now if compare with Person instantiation code below,
public Person CreateATestObject()
{
Person personObject = new Person()
{
Name = "M",
Profession = "Coding"
};
return personObject;
}
It is clear that How C# store Name and Profession property values at runtime.
+= and -= in Events
The definition of Event has been taken from MSDN. An event in C# is a way for a class to provide notifications to clients of that class when some interesting thing happens to an object.
The main point of this discussion is to discuss about, += (add) or -= (remove) syntax and how does it relates to the Event and delegate and also how does it work? Actually, the compiler translate += or -= into add or remove method in Layman’s terms. So to test the concept, I created small class (which is doing pretty much nothing),
public class LogIt
{
public delegate void LogHandler(string message);
public event LogHandler Log;
public Delegate[] GetList()
{
return Log.GetInvocationList();
}
}
So the above class has a delegate name LogHandler and event named Log of type LogHandler. The consumer of this class is as below,
public class AddRemoveHandlerOfEvent
{
public LogIt InitialiseLogIt()
{
LogIt logItObject = new LogIt();
logItObject.Log += new LogIt.LogHandler(Logger1);
logItObject.Log += new LogIt.LogHandler(Logger2);
logItObject.Log += new LogIt.LogHandler(Logger3);
return logItObject;
}
public void Logger1(string s)
{
Console.WriteLine(s);
}
public void Logger2(string s)
{
Console.WriteLine(s);
}
public void Logger3(string s)
{
Console.WriteLine(s);
}
}
So from the above consumer class we can see few methods such as Logger1, Logger2, Logger3 has been added to the Log of LogIt object. Now the question is where does these methods information stored or how does it works while use += or -= syntax. To answer the question again need to get help of .Net reflector. When we reflect the code we can see following code has generated by compiler for += or -=,
public class LogIt
{
public delegate void LogHandler(string message);
private LogHandler Log;
public event LogHandler Log
{
add
{
LogHandler handler2;
LogHandler log = this.Log;
do
{
handler2 = log;
LogHandler handler3 = (LogHandler) Delegate.Combine(handler2, value);
log = Interlocked.CompareExchange<loghandler>(ref this.Log, handler3, handler2);
}
while (log != handler2);
}
remove
{
LogHandler handler2;
LogHandler log = this.Log;
do
{
handler2 = log;
LogHandler handler3 = (LogHandler) Delegate.Remove(handler2, value);
log = Interlocked.CompareExchange<loghandler>(ref this.Log, handler3, handler2);
}
while (log != handler2);
}
}
public Delegate[] GetList()
{
return this.Log.GetInvocationList();
}
}
There are two new stuffs which is add and remove, need to explore now does add and remove works, from add block one line of code give us all the clue which is,
LogHandler handler3 = (LogHandler) Delegate.Combine(handler2, value);
and if we dig bit more with Combine method, we will find out something like below,
public static Delegate Combine(Delegate a, Delegate b)
{
if (a == null)
{
return b;
}
return a.CombineImpl(b);
}
The code block is from the Delegate class and also CombineImpl method called from Combine method is defined in the MulticastDelegate class.
The MulticastDelegate holds two variable
private IntPtr _invocationCount;
private object _invocationList;
and this _invocationList is the main object which holds all the method signature assigned using += syntax. From the below images we can see how does _ invocationList used to store all the method signature as method pointer(IntPtr)
Fig: _innvocationList of MulticastDelegate class
Fig: objArray at runtime.
Fig: In depth view of the objArray to find out method information from _ innvocationList
To get a clear view of this, I created a small test program to test, how .Net store all the method inside the _invocationList. If we see the below code block of the CombineImpl method,
public IEnumerable<string> GetInitialMethodPointer()
{
return GetType().GetMethods().Select(methodInfo => string.Format("{0,40}-->{1,20}", methodInfo.Name, methodInfo.MethodHandle.Value.ToString()));
}
public IEnumerable<string> GetInvocationListFrom(LogIt logItObject)
{
return logItObject.GetList().Select(delegateObject => string.Format("{0,40}-->{1,20}", delegateObject.Method.Name, delegateObject.Method.MethodHandle.Value.ToString()));
}
</string></string>
We can see, GetInitialMethodPointer method will show the initial methods pointer for Logger1, Logger2 and Logger3 and GetInvocationListFrom method will show what does _invocationList contains after using += operation to add method signneture. From the image below, it is clear that _invocationList contains exactly the same method pointer value we get from GetInitialMethodPointer.
Fig: Output of the method pointer store into _ innvocationList
The implementation of -= is also a bit of nice stuff to dissect. Following Call Stack will show how the remove calls from consumer code to all the way back into Delegate class to update _ invocationList list,
Fig: Call Stack of Delete Operation
And if we look into the RemoveImpl method code then we can see it called another method named DeleteFromInvocationList as below,
Fig: Inside of the RemoveImpl method
And code inside DeleteFromInvocationList will eventually update the _ invocationList list to update the current method signature after remove. Please see the following image,
Fig: Inside of DeleteFromInvocationList
So from the above discussion we have pretty good picture of how += and -= works for Events and Delegate.
If you interested detail about other features of the C# language,
Expert C# 5.0 with the .NET 4.5 Framework might be useful.
Limitation
- There is no discussion about how .Where, .Select extension methods work for a List.
Related Articles
History
Version 1.0
Reference