C# Language Enhancements


What is Var
  1. In the C# 'var' variables are called implicitly-typed local variables. 
  2. A var variable must be initialized when it is declared
  3. The compile-time type of the initializer expression must not be of null type but the runtime expression can be null.
  4. Once it is initialized its data type is fixed to the type of the initial data.
Valid statements

var a = "1"; // compile time not null, and is initialized
var b = 0;// compile time not null, and is initialized
string c = "string";
var c1 = c;// c is compile time not null, c1 is initialized c
c1 = null; // c1 compile time declared to c, so no issues
string c2 = null;
var c3 = c2; // compile time type is string

For the above var variables, IL will be like

string a = "1";
int b = 0;
string c1 = "string";
string c3 = null; 

Invalid statements

var x; //Error Implicitly-typed local variables must be initialized           
var y = null; Error Cannot assign <null> to an implicitly-typed
var z = "e"; z = 2; Error Cannot implicitly convert type 'int'to'string'

Object initialize

public class Product
{
    public int ProductID { get; set; }
    public string ProductName { get; set; }
    public decimal UnitPrice { get; set; }
}

We'll be able to create object as like

Product p = new Product
{
    ProductID = 1,
    ProductName = "Chinna",
    UnitPrice = 100
};

Collection initializer

Similar to object initializer we we'll also be able to create typed collection as follow

static void Main(string[] args)
{
    List<Product> products = new List<Product> {
        new Product{ ProductID=1, ProductName="A", UnitPrice=10},
        new Product{ ProductID=2, ProductName="B", UnitPrice=11},
    };
}

public class Product
{
    public int ProductID { getset; }
    public string ProductName { getset; }
    public decimal UnitPrice { getset; }
}

What are anonymous type

Anonymous types are reference types that derive directly from object. Anonymous types are handy C# feature that allow developers to encapsulate a set of properties into a single object without having to define a type before hand. The type's properties we define in an anonymous type are incidental by the compiler and are read-only.

Anonymous is used for short-term data manipulation.

Anonymous types have some limitations. 
  1. The properties are read-only, only properties can be defined, and not methods , and their scope is limited to the method in which they are created
  2. They cannot be passed as arguments to other methods. To pass an anonymous type, or a collection that contains anonymous types, outside a method boundary, you must first cast the type to object.
  3. They cannot be cast to any type except for object.
  4. Anonymous types cannot contain unsafe types as properties.
  5. Declare a variable using the special type var, and then define the type's content using the new keyword.
Example 1:

var anonymousType = new
{
    Name = "Srihari Chinna",
    City="Bangalore",
    EmploymentDetails = new {
        EmpId=1779,
        Emp = "Capgemini",
    }
};

Example 2: how to pass anonymous type to another method as a parameter

public void Method()
{
    var anonymousType = new
    {
        Name = "Srihari Chinna",
        City="Bangalore",
        EmploymentDetails = new {
            EmpId=1779,
            Emp = "Capgemini",
        }
    };
    object obj = (object)anonymousType;
    OtherMethod(obj);
}
public void OtherMethod(object obj)
{
    Type obj1 = obj.GetType();
    Console.WriteLine(obj1.GetProperty("Name").GetValue(obj, null));
}

What are Extension Methods

Extension methods enable developers to extend the functionality of any existing class by adding methods using extension methods without creating a new derived type, recompiling, or otherwise modifying the original type.

Extension methods are static methods, but they are instance methods on the extended type. That is they can be called on the extended type instance.

We can use extension methods to extend any class or interface, but we can't override a member. An extension method with the same name and signature as an interface or class method will never be called. Since static members can't be marked as override, virtual, or abstract, so for extension also.

Scope of extension methods are at the namespace level. If you have more than one static class that contain extension methods in a single namespace, all the extensions can be accessed at the namespace level.

Extension methods implement Decorator pattern
  1. Define a static class to contain the extension method. 
  2. Implement the extension method as a static method with at least the same visibility as the containing class.
  3. The first parameter of the method specifies the type that the method operates on; it must be preceded with the this modifier.
  4. In the calling code, add a using directive to specify the namespace that contains the extension method class.
  5. Call the methods as if they were instance methods on the type.
Why and where they can be used
  1. When a class is sealed, we can't inherit from it. In this case, we have no option but to use extension methods. 
  2. We want to implement a method that can be invoked on all classes implementing a given interface; before, we had no way to attach a method implementation to an interface. 
  3. We may want to add related things to a number of other classes, and from a software engineering point of view it may be better to collect those together in one place rather than spreading them amongst many classes.
Example 1:

Custom class for which we want to implement extension method

namespace  Objects
{
    public class SomeClass    {
        public void Method()        {
            Console.WriteLine("Class C method is called");
        }
        public void Method(Object obj)        {
           Console.WriteLine("Class C method one is called");
        }
    }
}

namespace CustomeExtensions{
    public static class MyExtensions    {
        public static void Method(this Objects.SomeClass someClass)        {
            Console.WriteLine("Extension method is called");       
        }
    }
}

Client

SomeClass someClass = new SomeClass();
someClass.Method();

1.gif
 
In this case method from SomeClass and extension method are matching in the signature so extension method will never be called. So we can only find two overloaded methods in SomeClass.

Example 2:

Custom class for which we want to implement extension method

namespace  Objects{
    public class SomeClass    {
        public void Method()        {
            Console.WriteLine("Class C method is called");
        }
        public void Method(Object obj)        {
            Console.WriteLine("Class C method one is called");
        }
    }
}

namespace CustomeExtensions{
    public static class MyExtensions    {
        public static void Method(this Objects.SomeClass someClass, int i)
        {
            Console.WriteLine("Extension method is called");       
        }
    }
}

Client

SomeClass someClass = new SomeClass();
someClass.Method();

2.gif
 
In the above case client can see three methods.

Example 3:

Custom class for which we want to implement extension method

namespace  Objects{
    public class SomeClass    {
        public void Method()        {
            Console.WriteLine("Class C method is called");
        }
        public void Method(string obj)        {
            Console.WriteLine("Class C method one is called");
        }
    }
}

namespace CustomeExtensions{
    public static class MyExtensions    {
        public static void Method(this Objects.SomeClass someClass, int i)        {
                      MyExtensions.Method(10);
            Console.WriteLine("Extension method is called");       
        }
    }
}

Client

MyExtensions.Method(new SomeClass(),10);

It will be get into infinite loop. So make sure we are not calling the extension methods directly.