Click here to Skip to main content
Click here to Skip to main content

How does it work in C#? - Part 1

By , 20 Nov 2012
Rate this:
Please Sign up or sign in to vote.

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,


How_does_work_in_CSharp/VarAtDesignTime.PNG

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,

How_does_work_in_CSharp/OutputOfAutoImplementedProperties.PNG

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
{
    // Nested Types
    public delegate void LogHandler(string message);
    // Fields
    private LogHandler Log;
    // Events
    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);
        }
    }
    // Methods
    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)

How_does_work_in_CSharp/ObjectAsInvocationList.PNG

Fig: _innvocationList of MulticastDelegate class

How_does_work_in_CSharp/ObjectHoldInvocationList.PNG

Fig: objArray at runtime.

How_does_work_in_CSharp/EventAtRuntimeResized.PNG

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.

How_does_work_in_CSharp/EventsOutput.PNG
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,
How_does_work_in_CSharp/RemoveEvents.PNG


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,
How_does_work_in_CSharp/RemoveInitialCode.PNG

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,
How_does_work_in_CSharp/InsideOfDeleteOperation.PNG

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

License

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

About the Author

Mohammad A Rahman
Software Developer
Australia Australia
Designer and Architect.
Author of the Expert C# 5.0: with the .NET 4.5 Framework book

Comments and Discussions

 
GeneralMy vote of 5 PinmemberHumayun Kabir Mamun18-Jul-13 23:40 
GeneralVery helpful Pinmemberbandi.ramesh15-Feb-13 22:17 
GeneralRe: Very helpful PinmemberMohammad A Rahman15-Feb-13 22:40 
Generalvar, LOL PinmemberJasmine250126-Nov-12 8:56 
GeneralRe: var, LOL PinmemberRanjan.D21-Jan-13 10:18 
GeneralRe: var, LOL PinmemberJasmine250121-Jan-13 11:15 
GeneralRe: var, LOL PinmemberRanjan.D21-Jan-13 11:53 
GeneralRe: var, LOL PinmemberJasmine250121-Jan-13 12:56 
GeneralRe: var, LOL PinmemberRanjan.D21-Jan-13 13:04 
GeneralRe: var, LOL PinmemberJasmine250122-Jan-13 5:11 
GeneralRe: var, LOL PinmemberRanjan.D28-Jan-13 8:22 
GeneralRe: var, LOL PinmemberPhilippe Mori13-Apr-13 13:47 
GeneralRe: var, LOL PinmemberJasmine250114-Apr-13 6:20 
GeneralRe: var, LOL PinmemberSuper Lloyd17-Nov-13 16:29 
GeneralRe: var, LOL PinmemberJasmine250118-Nov-13 5:48 
GeneralMy vote of 5 Pinmemberfredatcodeproject22-Nov-12 6:22 
GeneralRe: My vote of 5 PinmemberMohammad A Rahman4-Feb-13 15:29 
GeneralMy vote of 5 Pinmemberjames_berry21-May-12 17:08 
GeneralRe: My vote of 5 PinmemberMohammad A Rahman21-May-12 17:39 
GeneralMy vote of 5 PinmemberJF201521-May-12 7:49 
GeneralRe: My vote of 5 PinmemberMohammad A Rahman21-May-12 17:38 
QuestionInitializer list produces more code that anticipated... PinmemberAndreas Gieriet24-Apr-12 2:49 
AnswerRe: Initializer list produces more code that anticipated... PinmemberMohammad A Rahman24-Apr-12 3:05 
QuestionVery interesting Pinmemberraulhmacias28-Mar-12 7:58 
AnswerRe: Very interesting PinmemberMohammad A Rahman28-Mar-12 10:46 

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

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

| Advertise | Privacy | Mobile
Web01 | 2.8.140421.2 | Last Updated 21 Nov 2012
Article Copyright 2011 by Mohammad A Rahman
Everything else Copyright © CodeProject, 1999-2014
Terms of Use
Layout: fixed | fluid