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
 

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
Member
Designer and Architect.
Author of the Expert C# 5.0: with the .NET 4.5 Framework book

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralVery helpfulmemberbandi.ramesh15 Feb '13 - 22:17 
Love this article
GeneralRe: Very helpfulmemberMohammad A Rahman15 Feb '13 - 22:40 
Thanks. If you want to read more, might be interested to read Expert C# 5.0: with the .NET 4.5 Framework book Smile | :)

Generalvar, LOLmemberJasmine250126 Nov '12 - 8:56 
Always been amused by var keyword... it's not dynamic typing, and as soon as you assign something, the var is a definite type... so using the var keyword does nothing other than hide the type, which you should know. VAR is lazy code writing, and I'll never support it.
GeneralRe: var, LOLmemberRanjan.D21 Jan '13 - 10:18 
I would say one has to know the usage of "var" , use it suitably when required. It looks like we should never use "var" at all but the real use of it comes when you are initializing a variable with an anonymous type of object.
 
Please refer the below link for more understanding
 
http://msdn.microsoft.com/en-us/library/bb384061.aspx[^]
 
Thanks,
Ranjan.D

GeneralRe: var, LOLmemberJasmine250121 Jan '13 - 11:15 
If the expression on the right hand side of the var doesn't evaluate to one type at compile time, it doesn't compile. So, what I'm saying is, instead of saying var, just put what that type is - the compiler knows what that type is, or it wouldn't compile, so as a programmer, you should take the next logical step - since it can only be one type, say what it is. Take this for example...
 
Object j;
if (myBool) {
j = new MyType();
} else {
j = new SomeOtherType();
}
 
That works - you have a variable which can be various types depending on logic. The same is not true of the var keyword... the following won't compile...
 
var j = myBool ? new MyType() : new SomeOtherType();
 
If j is type Object, that will work, but if the expression can return a choice of types, and those types don't have a common basetype other than Object, it won't work.
 
So again, I ask you, what is the point of the var keyword? The type must be known at compile time for var to compile, and if the type is known, you're just being lazy by not writing what it is.
 
I understand what you're saying about anonymous types, but again, I consider that lazy programming. Why create a temporary class that isn't documented and nobody knows what it is?
 
In other words... this...
 
var j = new { Order = 123, Product = 45 };
 
... is lazy programming. If you need an object with those fields, DEFINE IT.
 
That's my beef - I don't like things that aren't defined. I think it's lazy. Convenient, yeah, but lazy and should not be used for anything real.
GeneralRe: var, LOLmemberRanjan.D21 Jan '13 - 11:53 
As said one has to use "var" if required and not to use every where. There are reasons why we have to use, also it's extensively used in LINQ. There is nothing harm in defining your own type and if one uses "var" it's may not really be a lazy way of programming.
 
Here's an article you can refer to understand the usage of Anonymous types. http://www.west-wind.com/weblog/posts/2007/Nov/15/Anonymous-Types-in-C-30[^]
 
Also I see the usage of it when it comes to intermediate processing of types and I don;t really think of creating a class for each of these temporary types. Here's an example http://msdn.microsoft.com/en-us/vstudio/bb417257.aspx[^]
 
I believe Microsoft had throught well before putting these features as a part of the framework , so one has to really think off when to use. Also the argument is never ending for creating a class than using anonymous types.
 
Thanks,
Ranjan.D

GeneralRe: var, LOLmemberJasmine250121 Jan '13 - 12:56 
Right, yes... you're just hearing the opinion of an old-skool programmer who doesn't like that kind of thing. It isn't functionally or logically wrong, it's just ugly.
GeneralRe: var, LOLmemberRanjan.D21 Jan '13 - 13:04 
No It isn't ugly Frown | :( I prefer to use it when it's really required. I wounder if you are taking my interview you will reject me staying that I'm a lazy programmer Big Grin | :-D
 
You really have an amazing 20+ yrs of experience, I bow my head senior , Yes you are right in many aspects too Smile | :)
 
Thanks,
Ranjan.D

GeneralRe: var, LOLmemberJasmine250122 Jan '13 - 5:11 
No I wouldn't, I would be jealous of your comfort level with the new frameworks. I have been doing software for almost 30 years and in that time I've seen a lot of changes, some of which I've liked, some of which I don't like, but my personal feeling for something isn't as important as how does it fit to our needs. So, I've used things I didn't like, such as Ruby and Labview - because they were the best tools for the job. That's what experience gives you - the ability to put your personal feelings aside and get the job done. But, on CodeProject discussions that isn't really the case.
GeneralRe: var, LOLmemberRanjan.D28 Jan '13 - 8:22 
I'm back with one interesting article on the usage of dynamic keyword and how does it differ from var or object
 
http://www.techiesweb.net/dynamic-type-in-c4-0-where-and-how-to-use-how-does-it-differ-from-var-and-object/[^]
 
Thanks,
Ranjan.D

GeneralRe: var, LOLmemberPhilippe Mori13 Apr '13 - 13:47 
var keyword also make it lot easier to refactor code by renaming classes and namespace as you get far less changes to make.
 
In my opinion, it is also helpfull to avoid repetition. Repetition is bad and when type are long, it is worst. If you think that var keyword is bad, then you probably also thing that using namespace is bad and you have things like that in your code:
System.Collections.Generic.Dictionary<System.DateTime, System.Collections.List<string>> myVariable = 
   new System.Collections.Generic.Dictionary<System.DateTime, System.Collections.List<string>>()
I don't see any benefit in case like that to write the type twice. It is not more readable and harder to maintain as you have more work to do when refactoring code.
 
I do think that the following line is more readable than the previous sample...
var myVariable = new Dictionary<DateTime, List<string>>()
Philippe Mori

GeneralRe: var, LOLmemberJasmine250114 Apr '13 - 6:20 
Sure yeah, a feature that allows the programmer to be lazy can't possibly be all bad.
GeneralMy vote of 5memberfredatcodeproject22 Nov '12 - 6:22 
very good
GeneralRe: My vote of 5memberMohammad A Rahman4 Feb '13 - 15:29 
Thank you, you might be interested reading more inner details in here[^]

GeneralMy vote of 5memberjames_berry21 May '12 - 17:08 
Good one
GeneralRe: My vote of 5memberMohammad A Rahman21 May '12 - 17:39 
Thank you Smile | :)
GeneralMy vote of 5memberJF201521 May '12 - 7:49 
Good article. Thanks for posting.
GeneralRe: My vote of 5memberMohammad A Rahman21 May '12 - 17:38 
Thank you Smile | :)
QuestionInitializer list produces more code that anticipated...memberAndreas Gieriet24 Apr '12 - 2:49 
Hello Mohammad,
 
I think the var declaration is clear that it is determning the type at compile time. What is more interesting is the strange behaviour of the compiler which creates a temporary object if you use initializer list.
 
E.g.
    public class MyClass
    {
        public int Prop { get; set; }
        public MyClass() : this(default(int)) {}
        public MyClass(int i) { Prop = i; }
    }
...
    var a1 = new MyClass();
    var a2 = new MyClass(100);
    var a3 = new MyClass() { Prop = 200 };
 
    MyClass b1 = new MyClass();
    MyClass b2 = new MyClass(100);
    MyClass b3 = new MyClass() { Prop = 200 };
Results in
    MyClass a1 = new MyClass();
    MyClass a2 = new MyClass(100);
    MyClass <>g__initLocal0 = new MyClass();
    <>g__initLocal0.Prop = 200;
    MyClass a3 = <>g__initLocal0;
 
    MyClass b1 = new MyClass();
    MyClass b2 = new MyClass(100);
    MyClass <>g__initLocal1 = new MyClass();
    <>g__initLocal1.Prop = 200;
    MyClass b3 = <>g__initLocal1;
 
I would have expected that you elaborate on that a bit since this is the real interesting part of the story, I would say Wink | ;)
 
BTW: You seem to mix up what IDE's Intellisense does and what the compiler does.
What you see in the IDE is what Intellisense thinks it knows. This is not necessarily in line with what the compiler does (most of the time it will, though Wink | ;) )
 
Cheers
Andi
AnswerRe: Initializer list produces more code that anticipated...memberMohammad A Rahman24 Apr '12 - 3:05 
Dear Andi,
 
Thank you very much for your comments. I will keep this in my mind for the upcoming articles of this series Smile | :)
 
Mohammad
QuestionVery interestingmemberraulhmacias28 Mar '12 - 7:58 
Thanks for sharing this
Raul Macias

AnswerRe: Very interestingmemberMohammad A Rahman28 Mar '12 - 10:46 
Thank you Smile | :)
GeneralMy vote of 5membermanoj kumar choubey1 Mar '12 - 18:01 
Nice
GeneralMy vote of 1 [modified]memberJeremyKyle1 Mar '12 - 6:31 
Thanks

modified 6 Mar '12 - 12:38.

GeneralRe: My vote of 1memberMohammad A Rahman1 Mar '12 - 10:17 
Can you please advice me How can I improve this article?
GeneralMy vote of 5memberShahin Khorshidnia6 Feb '12 - 1:41 
A perfect explanation.
GeneralRe: My vote of 5memberMohammad A Rahman6 Feb '12 - 2:10 
Thank you very much Smile | :)
GeneralRe: My vote of 5memberGregoryW2 Mar '12 - 4:27 
I gave 5, but in my opinion you should write a bit more about encapsulation when u started to write about basics. Regards.
GeneralRe: My vote of 5memberShahin Khorshidnia2 Mar '12 - 5:13 
Why under my comment, GregoryW ? Confused | :confused:
Do not criticise, if you don't have any better idea.

GeneralRe: My vote of 5memberGregoryW2 Mar '12 - 5:14 
Sorry, my mistake. I didn't want to disturb your comment. Sorry Wink | ;)
GeneralRe: My vote of 5memberShahin Khorshidnia2 Mar '12 - 5:17 
No problem.
I just a little confused. Wink | ;)
Do not criticise, if you don't have any better idea.

GeneralRe: My vote of 5memberGregoryW5 Mar '12 - 0:11 
Sorry once again Wink | ;)
GeneralRe: My vote of 5memberMohammad A Rahman2 Mar '12 - 12:01 
Good suggestions. Smile | :)
SuggestionMy vote of 4memberReiss5 Feb '12 - 21:16 
Generally a really good article however, you may want to expand your section about Auto-Implemented Properties
 
1) To use them you must include both a get and a set operation for the field
 
public class Book
{
    public string Name { get; set;} // ok
    public string Author { get; } // won't compile
    public string ISBN { set; } // won't compile
}
 
2) The access modifiers can be different, e.g
 
public class Book
{
    public string Name 
    { 
        get; 
        private set; 
    }
}

GeneralRe: My vote of 4memberMohammad A Rahman5 Feb '12 - 21:26 
Thank you Smile | :)
QuestionMy vote of 5memberMizan Rahman26 Dec '11 - 5:31 
Very important article Smile | :)
AnswerRe: My vote of 5memberMohammad A Rahman26 Dec '11 - 11:32 
Thank you very much Smile | :)
GeneralMy vote of 5membernjdnjdnjdnjdnjd25 Dec '11 - 22:57 
Thank You
GeneralRe: My vote of 5memberMohammad A Rahman25 Dec '11 - 23:04 
Thank you very much Smile | :)
GeneralNice explanation.membersudhansu_k12325 Dec '11 - 18:33 
Very good article and nice explanation.
rudrakshafaqs[^]
GeneralRe: Nice explanation.memberMohammad A Rahman25 Dec '11 - 18:56 
Thank you Smile | :)
GeneralMy vote of 5memberrumpa_kazol15 Nov '11 - 22:01 
Great
GeneralRe: My vote of 5memberMohammad A Rahman17 Nov '11 - 6:29 
Thank you.
QuestionGood stuffmemberrumpa_kazol15 Nov '11 - 2:55 
It was a good reading.
AnswerRe: Good stuffmemberMohammad A Rahman15 Nov '11 - 3:11 
Thank you very much.
QuestionIt was a good effortmemberSharmin12315 Nov '11 - 2:53 
It was a good effort
AnswerRe: It was a good effortmemberMohammad A Rahman15 Nov '11 - 3:09 
Thank you very much
QuestionNice articlememberSazalsiddiqui15 Nov '11 - 2:29 
Nice article
AnswerRe: Nice articlememberMohammad A Rahman15 Nov '11 - 2:33 
Thank you very much.
GeneralMy Vote 5memberAbinash Bishoyi14 Nov '11 - 4:37 
Great Article

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

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