Extension Methods and Anonymous Types in C#

Discussion in 'C#' started by shabbir, Feb 16, 2014.

  1. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    In this article, we are going to explore a couple of fairly advanced C# concepts. We will start by explaining the concept of extension methods in C#. I will explain you with the help of examples, what basically extension methods are, how they are actually used and what its benefits are. Next, we will move towards another advanced concept of anonymous types in C#. After reading this tutorial you will be able to implement extension method and anonymous methods in your code and you will see how you can improve your code efficiency through them. So, let us get started with extension methods.

    Extension Methods



    If you have been programming for a while, you know well that a class contains method. A developer writes a class that performs certain functionality, encloses the class in a namespace and then ships the compiled assembly to the end user. What end user gets is compiled assembly to which he can reference at any time in order to achieve a particular functionality; he can modify the code unless the assembly is open source.

    But there exists a concept in C# which allows you to add new methods in existing C# class. This is basically the concept of extension methods. You have an existing class which performs certain functionalities; the class suffices your need except for one or two functions. Therefore, instead of writing a totally new class, you can use extension methods to add new methods to that existing class. Extension methods were added in C# 3.0.

    Extension methods are public static and can only be declared inside a static class. The first parameter of an extension method is always prefixed with the keyword this. We mentioned that extension methods actually extend an existing type. So what is that type which extension method extends? The answer to this question is that the type of the first parameter of extension methods is the type that extension methods extend by incorporating new extension method. All of this theory is best explained with the help of an Example. Have a look at our first example of this tutorial.

    Example1
    Code:
    using System.Linq;
    using System.Text;
    
    namespace CSharpTutorial
    {
        public static class StringExtender
        {
            public static bool FirstCapital(this string value)
            {
                if (!string.IsNullOrEmpty(value))
                {
                    return char.IsUpper(value[0]);
                }
                else
                    return false;
            }
        }
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Go4Expert".FirstCapital());
                Console.WriteLine("go4Expert".FirstCapital());
                Console.ReadLine();
            }
        }
    }
    
    In Example1, we have two classes. The first class is the static class named StringExtender. We named it string extender because this class will extend the string type. The StringExtender class contains one extension method named FirstCapital(), this method has only one parameter of type string which has been named as value. You can notice that this is the first and only parameter therefore we have prefixed it with the keyword this. The type of first parameter is string; therefore it will extend the string type. There is only one difference in the declaration of a normal public static method and extension method and that is the use of this keyword with the first parameter.

    Inside our extension method First Capital, we first check if the string is empty or null; if it is empty we straight forwardly return false. If the string is not empty or null, we then check whether the first letter of the string that has been passed is capital or not, if it is capital, true will be returned, otherwise false. In simplest word, we have extended our string class with a method which checks whether the first letter of the string is capital or not.

    Now, coming towards the main method where inside the main method we call our FirstCapital method on two strings, first which starts with capital and the other which doesn’t start with capital. We have called extension method twice in our code in following lines.
    Code:
    Console.WriteLine("Go4Expert".FirstCapital());
    Console.WriteLine("go4Expert".FirstCapital());
    
    The output of the call to the extension method will be true and false for both strings respectively, which have been printed on the screen.

    Behind the scene compiler converts the extension method to ordinary static method during compilation. For example consider the following call
    Code:
    Console.WriteLine("Go4Expert".FirstCapital());
    The compiler will translate this call to something like
    Code:
    Console.WriteLine(StringExtender.FirstCapital("Go4Expert"));
    The above line is an ordinary static method call to the FirstCapital method of StringExtender class. Whereas the former was the extension method call.

    Chaining Extension Methods



    Extension methods are similar to instance method in all respects except for behavior and this keyword with the first parameter. You can chain normal instance method. Method chaining means calling the method in series by appending them with each other. Method chaining on extension methods can be best explained with the help of an example. Have a look at

    Example2
    Code:
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace CSharpTutorial
    {
        public static class StringExtender
        {
            public static string FirstCapital(this string value)
            {
                if (string.IsNullOrEmpty(value))
                    return string.Empty;
                char[] capstring = value.ToCharArray();
                capstring[0] = char.ToUpper(capstring[0]);
                return new string(capstring);
            }
    
            public static string LastCapital(this string value)
            {
                if (string.IsNullOrEmpty(value))
                    return string.Empty;
                char[] capstring = value.ToCharArray();
                capstring[value.Length - 1] = char.ToUpper(capstring[value.Length - 1]);
                return new string(capstring);
            }
        }
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Actual String: go4Expert");
                Console.WriteLine("go4Expert".FirstCapital()+": First Capital");
                Console.WriteLine("go4Expert".LastCapital()+": Last Capital");
                Console.WriteLine("go4Expert".FirstCapital().LastCapital()+": First and Last Capital");
                Console.ReadLine();
            }
        }
    }
    
    Have a look at Example2. We have a static class named StringExtender. This class now contains two extension methods. The first one is FirstCapital, this method takes a string as an argument and then converts the first letter of the passed string into a capital letter and then returns that string back. The second method is another extension method which we have named LastCapital. This method will capitalize the last letter of the passed string and will return the string back to the calling function.

    Inside the main method of class Program, we have first call the FirstCapital method on string go4Expert and displayed it. Next we have called LastCapital method on the same go4Expert string and displayed the output on the string.

    In the next line following line of code is the gist of this section.

    Code:
    "go4Expert".FirstCapital().LastCapital()
    In the above line of code, we are actually chaining two extension methods like we chain ordinary static methods. What is actually happening here is that we have first called FirstCapital method on string “go4Expert”, the result of this method call will be another string which will be “Go4Expert”, you can see that first letter of go4Expert has been capitalized. Next we have chaining LastCapital method with the FirstCapital method using dot operator. However, LastCapital method will receive the output of the FirstCapital method which will be “Go4Expert”. When LastCapital method is called on that string it will capitalize the last letter of that string and the output would be Go4ExperT where both the first letter G and the last letter T would be capitalized. The output of Example2 is as shown.

    Output

    [​IMG]

    In both of our Examples: Example1 and Example2, we had the class of the extension method in the same namespace in which we are calling those extension methods. You can see that both the StringExtender class containing the extension methods and the Program class where we are calling these methods are located in the same namespace CSharpTutorial.

    However, If the class containing extension methods is located in some other namespaces for instance CSharpTutorial2 and we want to use those extension methods in a class which is encapsulated in a namespace other than CSharpTutorial2, we will have to import the CSharpTutorial2 namespace in that class.

    Extension Method Precedence



    Extension methods are extremely interesting phenomena. Consider a scenario where a namespace has two static classes with an extension method with similar signature. When you call the extension method, which method will be called? This is best explained with the help of Example. Have a look at Example three to further grasp this concept.

    Example3

    Code:
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace CSharpTutorial
    {
        public static class StringExtender
        {
            public static string Capitalize(this string value)
            {
                if (string.IsNullOrEmpty(value))
                    return string.Empty;
                char[] capstring = value.ToCharArray();
                capstring[value.Length -1] = char.ToUpper(capstring[value.Length - 1]);
                return new string(capstring);
            }
        }
        public static class StringExtender2
        {
            public static string Capitalize(this object value)
            {
                if (string.IsNullOrEmpty(value.ToString()))
                    return string.Empty;
                char[] capstring = value.ToString().ToCharArray();
                capstring[0] = char.ToUpper(capstring[0]);
                return new string(capstring);
            }
        }
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Actual String: go4Expert");
                Console.WriteLine("go4Expert".Capitalize());
                Console.WriteLine(StringExtender2.Capitalize("go4Expert"));
                Console.ReadLine();
            }
        }
    }
    
    In Example3, we have modified Example2. We have a single namespace CSharpTutorial which now contains three classes: StringExtender, StringExtender2 and Progam class which contains main method. Inside class StringExtender we have a method named Capitalize which received one argument of type string. This Capitalize method of StringExtender class will capitalize the last letter of the passed string and will return that string. Next we have another class StringExtender2 which contains also contain one method Capitalize which takes object type as parameter and converts that object into string. It then capitalizes the first letter of the sting and then returns that string.

    Now, a question here arises that when we call Capitalize method on any string, which capitalize method would be called because string will match the parameter of the StringExtender’s Capitalize method that takes string as an argument. The string argument will also match the parameters of the Capitalize method of StringExtender class that takes object as parameter. As we know that object type variable can hold object of any type, therefore string can also be stored in it. You must be thinking, then which Capitalize method would be called.

    The answer Is that when you have multiple extension methods with similar signature in different classes, the method which has more specific parameter would be called. Therefore the Capitalize method of StringExtender class because it has a more specific parameter string as compared to object parameter of the Capitalize method of StringExtender2 class. In order to call the Capitalize method of StringExtender2 class, you will have to call it as ordinary static method with the class name. We have done this in the main method of the Example3. The output of Example3 is as follows.

    Output3

    [​IMG]

    In Example 3, the parameters of the two Capitalize methods were different, what if parameters of both Capitalize methods are same? In that case you will have to explicitly call the method that you want to execute, like you call simple instance methods.

    Anonymous Types



    Sometimes, you don’t want a type to be stored in your memory for a long time. You need a type somewhere in your class which you use once and throw it. In such cases, .NET framework allows you to develop anonymous types. Anonymous types are types that are created on the fly like

    Code:
    var person = new {Name=”james”, Gender= “male”};
    In order to create anonymous types, keyword new is used as shown in the previous line. Another important thing to remember is that instance of anonymous type must be stored in the variable of type var because we don’t know what the type of anonymous type object is.
    When compiler reaches the aforementioned line of code, it will convert these lines into

    Code:
        internal class AnonymousGeneratedTypeName
        {
    
            private string name; // Actual name of the field is not relevant
            private string gender;  // Actual name of the field is not relevant
    
            public AnonymousGeneratedTypeName(string name, string gender)
            {
                this.name = name;
                this.gender = gender;
            }
            public string Name { get { return name; } }
            public string Gender { get { return gender} }
    
        }
        var person = new AnonymousGeneratedTypeName("james", "male")
    
    ToString, GetHashCode and Equals method are overriding in case of anonymous types. Let’s have a look at simple example of anonymous types. Consider Example4.

    Example4
    Code:
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace CSharpTutorial
    {
        class Program
        {
            static void Main(string[] args)
            {
                var person = new {Name ="james", Gender= "male"};
                Console.WriteLine(person.Name);
                Console.WriteLine(person.Gender);
                Console.ReadLine();
            }
        }
    }
    
    This is a simple example of usage of anonymous types, we created an anonymous type and stored it in person object of type var and then we have accessed the member of that anonymous type and displayed them on output screen. You can see we have accessed the member using dot operator in similar to how we access the member variables of regular types. The output of Example4 is as follows.

    Output4

    [​IMG]
     
    Last edited: Jan 21, 2017

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice