Sunday 7 July 2013

C# new features

C# 3.0 new features

In this part of the C# tutorial, we will talk about some of the new features of the C# version 3.0. Microsoft introduced this version of the C# in August 2007. Mono C# compiler fully supported the new version by July 2008.
The C# 3.0 version brought the following new features to the language:
  • Implicitly typed variables
  • Implicitly typed arrays
  • Object & collection initializers
  • Automatic properties
  • Anonymous types
  • Extension methods
  • Query expressions
  • Lambda expressions
  • Expression trees
Query expressions, lambda expressions and expression trees are beyond the scope of this tutorial. They are closely connected to the LINQ.

Implicitly typed local variables & arrays

Both implicitly typed local variables & arrays are connected with the var keyword. It is an implicit data type. In some cases, we do not have to specify the type for a variable. This does not mean, that C# is partially a dynamic language. C# remains a statically and strongly typed programming language. Sometimes, when the usage of the var keyword is allowed, the compiler will find and use the type for us.
In some cases, the var keyword is not allowed. It can be used only on a local variable. It cannot be applied on a field in a class scope. It must be declared and initialized in one statement. The variable cannot be initialized to null.
using System;

public class CSharpApp
{
    static void Main()
    {
        int x = 34;
        var y = 32.3f;
      
        var name = "Jane";
 
        Console.WriteLine(x);
        Console.WriteLine(y.GetType());
        Console.WriteLine(name.GetType());
    }
}
We have a small example, where we use the var type.
int x = 34;
var y = 32.3f;
The first variable is explicitly typed, the second variable is implicitly typed. The compiler will look at the right side of the assignment and infer the type of the variable.
Console.WriteLine(y.GetType());
Console.WriteLine(name.GetType());
These two lines will check the type of the two variables.
$ ./itlv.exe 
34
System.Single
System.String
As we can see, the two variables use the familiar, built-in data types.

Implicitly typed arrays Implicitly typed arrays are arrays, in which the type of the array is inferred from the elements of the array in the array initializer by the compiler. The rules are the same as for implicitly typed local variables. Implicitly typed arrays are mostly used in query expressions together with anonymous types and object and collection initializers.
using System;

public class CSharpApp
{
    static void Main()
    {
        var items = new[] { "C#", "F#", "Python", "C" };

        foreach (var item in items)
        {
            Console.WriteLine(item);
        }
    }
}
An example demonstrating the implicitly typed arrays.
var items = new[] { "C#", "F#", "Python", "C" };
We again use the var keyword. The square brackets on the left side are omitted.
foreach (var item in items)
{
    Console.WriteLine(item);
}
The foreach loop is used to traverse the array. Note the use of the local implicitly typed item variable.
$ ./ita.exe 
C#
F#
Python
C
Output.

Object initializers

Object initializers give a new syntax for creating and initiating objects. Inside a pair of curly brackets {} we initiate members of a class through a series of assignments. They are separated by comma character.
using System;

public class Person 
{
    private string _name; 
    private int _age;

    public string Name
    {
        get { return _name; }
        set { _name = value;} 
    }

    public int Age
    {
        get { return _age; }
        set { _age = value;} 
    }

    public override string ToString()
    {
        return String.Format("{0} is {1} years old", _name, _age);
    }
}

public class CSharpApp
{
    static void Main()
    {
        Person p1 = new Person();
        p1.Name = "Jane";
        p1.Age = 17;

        Person p2 = new Person { Name="Becky", Age=18 };

        Console.WriteLine(p1);
        Console.WriteLine(p2);
    }
}
In the above example, we have a Person class with two properties. We create two instances of this class. We use the old way and we also use the object initializer expression.
public string Name
{
    get { return _name; }
    set { _name = value;} 
}
This is a Name property, with set a get accessors.
Person p1 = new Person();
p1.Name = "Jane";
p1.Age = 17;
This is the old way of creating an object and initiating it with values using the field notation.
Person p2 = new Person { Name="Becky", Age=18 };
This is the object initializer. Inside curly brackets, the two members are initiated.

Collection initializers

Collection initializers are a way of initiating collections, where the elements of a collection are specified inside curly brackets.
List <string> planets = new List<string>();

planets.Add("Mercury");
planets.Add("Venus");
planets.Add("Earth");
planets.Add("Mars");
planets.Add("Jupiter");
planets.Add("Saturn");
planets.Add("Uranus");
planets.Add("Neptune");
This is the classic way of initiating a collection. In the following example, we will use a collection initializer for the same generic list.
using System;
using System.Collections.Generic;

public class CSharpApp
{
    static void Main()
    {
        List <string> planets = new List <string> 
            {"Mercury", "Venus", "Earth", "Mars", "Jupiter",
              "Saturn", "Uranus", "Neptune"};


        foreach (string planet in planets)
        {
            Console.WriteLine(planet);
        }
    }
}
We create a generic list of planets.
List <string> planets = new List <string> 
    {"Mercury", "Venus", "Earth", "Mars", "Jupiter",
      "Saturn", "Uranus", "Neptune"};
This is the collection initializer expression. The planet names are specified between the curly brackets. We save a some typing. We do not need to call the Add() method for each item of the collection.
$ ./collectioninitializers.exe 
Mercury
Venus
Earth
Mars
Jupiter
Saturn
Uranus
Neptune
Output.

Automatic properties

In a software project, there are lots of simple properties, that only set or get some simple values. To simplify programming and to make the code shorter, automatic properties were created. Note that we cannot use automatic properties in all cases. Only for the simple ones.
using System;


public class Person 
{
    public string Name { get; set; }
    public int Age { get; set; }
}

public class CSharpApp
{
    static void Main()
    {
        Person p = new Person();
        p.Name = "Jane";
        p.Age = 17;
        
        Console.WriteLine("{0} is {1} years old", 
            p.Name, p.Age);
    }
}
This code is much shorter. We have a person class in which we have two properties.
public string Name { get; set; }
public int Age { get; set; }
Here we have two automatic properties. There is no implementation of the accessors. And there are no member fields. The compiler will do the rest for us.
Person p = new Person();
p.Name = "Jane";
p.Age = 17;

Console.WriteLine("{0} is {1} years old", 
    p.Name, p.Age);
We normally use the properties as usual.
$ ./automatic.exe 
Jane is 17 years old
Output of the example.

Anonymous types

The class Person, that we use here is said to be a type. More specifically, it is a user defined type. The type has a name and we can explicitly create an instance of it by referring to its name. Anonymous types are types, that do not have a name. They are class types that consist of one or more public read-only properties. No other kinds of class members are allowed. Anonymous types are created with the new keyword and object initializer. The compiler will infer the types of the properties itself. It will give the type a name, but it is only used by the compiler; it is not available to the programmer. In fact, at compile type, the compiler generates a type from the anonymous type expression. And at runtime, an object is created out of the type.
using System;


public class CSharpApp
{
    static void Main()
    {
        var p = new {Name="Jane", Age=17};

        Console.WriteLine("{0} is {1} years old", p.Name, p.Age);
    }
}
An anonymous type example.
var p = new {Name="Jane", Age=17};
An anonymous object initializer declares an anonymous type and returns an instance of that type. We use the var keyword, because we do not know the type.
Console.WriteLine("{0} is {1} years old", p.Name, p.Age);
We access the properties created using the field access notation.
$ ./anonymoustype.exe 
Jane is 17 years old
Output.

Extension methods

Developers often face situations, in which they would like to extend an existing type, but it is not possible. For example, the class is sealed. The extension method is a workaround for such cases. Extension methods are a special kind of a static method, but they are called as if they were instance methods on the extended type. To create an extension method, we need a static class and a static method. When we call our extention method on a class, the compiler does some behind the scenes processing; for us it appears as if we have called the extension method on the object of a type.
It is also possible, and it was a common workaround in the past, to create special utility classes for such methods. These were mostly created as static methods of static classes. Both approaches have their advantages. It is also advised to use extension methods sparingly.
using System;

public static class Util
{
  public static string Reverse(this string input)
  {
    char[] chars = input.ToCharArray();
    Array.Reverse(chars);
    return new String(chars);
  }
}

public class CSharpApp
{
    static void Main()
    {
        string str1 = "Jane";
        string str2 = str1.Reverse();

        Console.WriteLine(str2);  
    }
}
In our case, we would like to add a new method for a String class. The String class is a built-in class and it is sealed. No inheritance is possible. This is why we need an extension method.
public static class Util
{
  public static string Reverse(this string input)
  {
    char[] chars = input.ToCharArray();
    Array.Reverse(chars);
    return new String(chars);
  }
}
We have a Reverse() extension method. This method reverses characters of a string variable. The method and its class must be static. The static Reverse() method becomes an extension method, when we put the this modifier as the first parameter of the method.
string str1 = "Jane";
string str2 = str1.Reverse();
We define and initialize a string variable. We call the Reverse() method on this variable. Even though the method is static, we use the instance method call syntax.
$ ./extentionmethods.exe 
enaJ
Output.
This part of the C# tutorial we have talked about new features of the C# 3.0.

C# 4.0 new features

In this part of the C# tutorial, we will talk about some of the new features of the C# version 4.0. Microsoft introduced this version of the C# in April 2010 with Visual Studio 2010. Mono C# compiler fully supported the new version by October 2010 with the release of Mono 2.8.
The C# 4.0 version brought the following new features to the language:
  • Dynamic programming
  • Named parameters
  • Optional parameters
  • Covariance and Contravariance

Dynamic programming

This new version of the C# language brought a new type dynamic. Once a variable is declared as having type dynamic, operations on these value are not done or verified at compile time, but instead happen entirely at runtime. This is known also as duck typing. The name of the concept refers to the duck test, which may be phrased as follows: "When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck". In other words, we are concerned about what the object is doing rather than with the type of the object. The dynamic type is used to simplify access to COM objects, IronPython and IronRuby libraries and to the HTML DOM.
using System;


public class Duck
{
    public void quack()
    {
        Console.WriteLine("Quaaaack");
    }
}

public class Person
{
    public void quack()
    {
        Console.WriteLine("Person imitates a duck");
    }
}


public class CSharpApp
{
    static void Main() 
    {
        Duck donald = new Duck();
        Person josh = new Person();
       
        InTheForest(donald);
        InTheForest(josh);
    }

    public static void InTheForest(dynamic duck)
    { 
        duck.quack();
    }
}
In our example, we have two classes. The Duck class and the Person class. Both have the quack() method.
public static void InTheForest(dynamic duck)
{ 
    duck.quack();
}
The InTheForest() method has a dynamic parameter. The type of the object is not important; we are concerned about capabilities of the objects. If objects passed to the InTheForest() method can invoke the quack() method, than we are fine.
$ dmcs ducktyping.cs
$ /usr/local/bin/mono ducktyping.exe 
Quaaaack
Person imitates a duck
We compile and run the program. We use the Mono dmcs compiler, that is shipped with the Mono 2.8 and supports the C# 4.0 profile.

Named parameters

In earlier versions of the C# language, the arguments were provided in the order in which they appeared in the method's signature. And the position in the parameter list is important when evaluating a method. Named arguments enable us to specify the method parameters by their names. When specifying the named arguments, the position of the parameter is not important anymore.
using System;


public class CSharpApp
{
    static void Main() 
    {
        ShowMessage(name: "Jane", age: 17);
    }

    public static void ShowMessage(int age, string name)
    {
        Console.WriteLine("{0} is {1} years old", name, age);
    }
}
A simple example with named arguments.
ShowMessage(name: "Jane", age: 17);
The parameter name is followed by the colon (:) character and the value. The parameters may not be specified in order of the method signature.
$ /usr/local/bin/mono named.exe 
Jane is 17 years old
Output.

Optional parameters

With C# 4.0 there are required parameters and optional parameters. Any call must provide arguments for all required parameters, but can omit arguments for optional parameters. Optional parameters are defined at the end of the parameter list, after any required parameters. An optional parameter is created, when when a default value is specified for the parameters.
using System;


public class CSharpApp
{
    static void Main() 
    {
        Power(4, 4);
        Power(5);
    }

    public static void Power(int x, int y=2)
    {
        int z = 1;

        for (int i=0; i<y; i++)
        {
            z *= x;
        }

        Console.WriteLine(z);
    }
}
An example for an optional argument. We have a Power() method. The method takes two parameters; the base and the exponent. If we do not specify the exponent, than the default 2 is used.
public static void Power(int x, int y=2)
In the method definition, we have a required x parameter and the optional y parameter. The optional y has a default value.
Power(4, 4);
Power(5);
When we call the Power() method, we can specify one or two parameters.
$ /usr/local/bin/mono optional.exe 
256
25
Output of the example.

Covariance & contravariance

C# version 4.0 brings covariance for generics and delegate types. They were introduced because they bring flexibility to programming. Within the type system of a programming language, covariance and contravariance refers to the ordering of types from narrower to wider and their interchangeability or equivalence in certain situations (such as parameters, generics, and return types). (wikipedia)
Types that are
  • covariant: convert from wider (double) to narrower (float).
  • contravariant: convert from narrower (float) to wider (double).
  • invariant: are not able to convert (Null).
using System;


public class CSharpApp
{
    static void Main()
    {
        string[] langs = {"C#", "Python", "PHP", "Java"};
        object[] objs = langs;

        object o1 = objs[1];
        Console.WriteLine(o1);
    }
}
Arrays are covariant from the beginning.
string[] langs = {"C#", "Python", "PHP", "Java"};
We have an array of string.
object[] objs = langs;
We assign a wider array of strings to a narrower object type.
object o1 = objs[1];
Console.WriteLine(o1);
We get an item and print it to the console.
$ ./covariance.exe 
Python
Output of the array covariance example.

In the following example, we have a covariance for generics.
using System;
using System.Collections.Generic;


public class CSharpApp
{
    static void Main()
    {
        IEnumerable<string> strings = new List<string>() {"1", "3", "2", "5"};
        PrintAll(strings); 
    }

    static void PrintAll(IEnumerable<object> objects)
    {
        foreach (object o in objects)
        {
          System.Console.WriteLine(o);
        }
    }
}
We have a generic list of strings. We call then the PrintAll() method, which prints all the elements of the list. Note that the method parameter has a less derived type parameter that our generic list.
$ /usr/local/bin/mono covariance2.exe 
1
3
2
5
Output.

The following is an example for a covariance in delegates.
using System;
using System.Collections.Generic;


public class CSharpApp
{
    static void Main()
    { 
        Action<string> del = ShowMessage; 
        del("Proximity alert");         
    }

    static void ShowMessage(object message) 
    { 
        Console.WriteLine(message);
    }
}
We assign a method which has a narrower parameter type to a delegate, which has a wider parameter type.
$ /usr/local/bin/mono contravariance.exe 
Proximity alert
Output.
This part of the C# tutorial we have talked about new features of the C# 4.0.

Introduction of New Features in C# 5.0

1. C# Evolution Matrix
Microsoft just published a new version of C# : 5.0 beta with CLR version 4.5 (Visual Studio 11 beta).
In order to get a big picture of the whole evolution of C# language, I summarized all the key features
into a C# Evolution Matrix for your reference as below diagram shows:


In C# version 5.0, there are two key features: Async Programming and Caller Information.
2. Async Feature
Two new key words are used for Async feature: async modifier and await operator. Method marked
with async modifier is called async method. This new feature will help us a lot in async programming.
For example, in the programming of Winform, the UI thread will be blocked while we use
HttpWebRequest synchronously request any resource in the Internet. From the perspective of user
experience, we cannot interact with the form before the request is done.
private void
btnTest_Click(object sender, EventArgs e)

{

var request = WebRequest.Create(txtUrl.Text.Trim());

var content=new MemoryStream();

using (var response = request.GetResponse())

{

using (var responseStream = response.GetResponseStream())

{

responseStream.CopyTo(content);

}

}

txtResult.Text = content.Length.ToString();

}


In the above example, after we clicked the Test button, we cannot not make any change to the form
before the txtResult textbox shows the result.
In the past, we can also use BeginGetResponse method to send async request as this sample in MSDN
shows:
http://msdn.microsoft.com/zh-cn/library/system.net.httpwebrequest.begingetresponse(v=vs.80).aspx. But it
will takes us a lot effort to realize it.
Now, we can simply use below code to do request asynchronously :
private async void
btnTest_Click(object sender, EventArgs e)

{

var request = WebRequest.Create(txtUrl.Text.Trim());

var content = new MemoryStream();

Task<WebResponse> responseTask = request.GetResponseAsync();

using (var response = await responseTask)

{
using (var
responseStream = response.GetResponseStream())

{

Task copyTask = responseStream.CopyToAsync(content);

//await operator to supends the excution of the method until the task is completed. In the meantime,
the control is returned the UI thread.

await copyTask;

}

}

txtResult.Text = content.Length.ToString();

}
The await operator is applied to the returned task. The await operator suspends execution of the
method until the task is completed. Meanwhile, control is returned to the caller of the suspended
method.
3. Caller Information
Caller Information can help us in tracing, debugging and creating diagnose tools. It will help us
to avoid duplicate codes which are generally invoked in many methods for same purpose, such
as logging and tracing.
We could get the below information of caller method :
Below example are a common practice prior to the new feature of Caller Information:
using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;
namespace
ConsoleApplicationTest

{

class Program

{

static void Main(string[] args)

{

InsertLog("Main");

MethodB();

Console.ReadLine();

}
static void MethodA()


{

InsertLog("MethodA");

MethodB();

}
static void MethodB()


{ }
static void
InsertLog(string methodName)

{

Console.WriteLine("{0} called method B at {1}", methodName,
DateTime.Now);

}

}

}
In both Main and MethodA methods, method InsertLog is invoked for logging. Now we can change the
codes to be as per below lines:
using System;

using System.Collections.Generic;

using System.Linq;

using System.Runtime.CompilerServices;

using System.Text;

using System.Threading.Tasks;
namespace
ConsoleApplicationTest

{

class Program

{

static void Main(string[] args)

{

//InsertLog("Main");

MethodB();

Console.ReadLine();

}
static void MethodA()


{

//InsertLog("MethodA");

MethodB();

}
static void MethodB(

[CallerMemberName] string memberName = "",

[CallerFilePath] string sourceFilePath = "",

[CallerLineNumber] int sourceLineNumber = 0)

{

InsertLog(memberName);

}
static void
InsertLog(string methodName)

{

Console.WriteLine("{0} called method B at {1}", methodName,
DateTime.Now);

}

}

}
4. Summary
The new features in C# 5.0 will help us to code more easily and improve the productivity. Have a nice
experience with the new release of Visual Studio 11!

No comments:

Post a Comment