Pages

Men

rh

6/16/2012

New Features of C# 3.0


New Features of C# 3.0 :-
  • Anonymous Types
  • Extension Methods 
  • Object Initializers
  • Collection Initializers
  • Implicitly typed local Variable
  • Lambda Expressions
  • Expression Trees
  • Linq Query Expression pattern
  • Auto-Implement Properties
  • Partial  Methods

Anonymous types in C# 3.0
  • Anonymous types are particularly useful when querying and transforming data with LINQ.
  • You create anonymous types by using the new operator together with an object initializer.
  • Anonymous types typically are used in the select clause of a query expression to return a subset of the properties from each object in the source sequence.
  • Anonymous types contain one or more public read-only properties. No other kinds of class members, such as methods or events, are valid.
  • The most common scenario is to initialize an anonymous type with properties from another type.
  •  If you do not specify member names in the anonymous type, the compiler gives the anonymous type members the same name as the property being used to initialize them. You must provide a name for a property that is being initialized with an expression.
Example


class TheCar

private string make;

public string Make
{
  get
  { return make; }
  Set
  {make = value; }
  }
Private string model;

Public string Model
 {
    get { return model; }
    Set { model = value; }
  }
}

To create an instance of this class and set the properties we would write

TheCar mycar = new TheCar ();
mycar.Make = “Fiat”;

mycar.Model = “Fiat Punto”;

Using the object initialization syntax we can write the following statement

var mycar=new TheCar{Make=”Fiat”,Model=”Fiat punto”}; 

With anonymous types I would rewrite the statement above to this

var mycar=new {Make=”Fiat”,Model=”Fiat punto”}; 


Remarks:
  • Anonymous types are class types that derive directly from object, and that cannot be cast to any type except object. The compiler provides a name for each anonymous type, although your application cannot access it.
  • If two or more anonymous types in the same assembly have the same number and type of properties, in the same order, the compiler treats them as the same type. They share the same compiler-generated type information.
  • You cannot declare a field, a property, an event, or the return type of a method as having an anonymous type.
  • you cannot declare a formal parameter of a method, property, constructor, or indexer as having an anonymous type.
  • To pass an anonymous type, or a collection that contains anonymous types, as an argument to a method, you can declare the parameter as type object.
  • Extension Methods:
  • Extension methods allow you to easily extend a type, such as an integer or string, without re-compiling or modifying the type. In essence, they are a type of static (shared in VB) method, but they are called as if the method is native to the type. Extension methods are available from the 3.5 version of the .NET Framework and can be implemented on any type in the .NET Framework or any custom type that you define.
  • You can use extension methods to extend a class or interface, but not to override them. An extension method with the same name and signature as an interface or class method will never be called.
  • One downside to extension methods is if that you create an extension method with the same name as another method in that type, the compiler will bind the method call to the native method, not any extension. An extension method is only called when there is no native method found.
  • Remember the following two points while implementing extension methods for a given type:
  • An extension method will never be called if it has the same signature as a method defined in the type.
  •  Extension methods are brought into scope at the namespace level. For example, if you have multiple static classes that contain extension methods in a single namespace named Extensions, they will all be brought into scope by the using Extensions; directive.

How Do We Create Extension Methods?

The basic outline of creating extension methods goes something like this:
  1. Create a public static class (module in VB) 
  2. Define functions that you wish to perform
  3. Make the functions an extension method
public static class Extensions
{
 
}
The next phase would be to write the function that we are going to need, which in this case is the following:
 
public static class Extensions
{
    public string GetFirstThreeCharacters(String str)
    {
        if(str.Length < 3)
        {
            return str;
        }
        else
        {
            return str.Substring(0,3);
        }
    }
}

To make our C# version of our function, we need an extension method to mark the function as static (so that it can be accessed at any time without the need for declaring anything) and secondly, mark the first parameter with the this keyword. This keyword basically tells the CLR that when this extension method is called, to use "this" parameter as the source. See the following:
public static class Extensions
{
   String str = "my new String";
   str = str.GetFirstThreeCharacters();
 
    public static string GetFirstThreeCharacters(this String str)
    {
        if(str.Length < 3)
        {
            return str;
        }
        else
        {
            return str.Substring(0,3);
        }
    }
}
 
 

Benefits of extension methods
  • Extension methods allow existing classes to be extended without relying on inheritance or having to change the class's source code.
  • If the class is sealed than there in no concept of extending its functionality. For this a new concept is introduced i.e. extension methods.
  • This feature is important for all developers especially if you would like to use the dynamism of the C# enhancements to be taken place in your classes design. 

Example:

using
System;
using
System.Text;

namespace
ExtensionMethod2
{
    public static class ExtMetClass
    {
        public static int IntegerExtension(this string str)
        {
            return Int32.Parse(str);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            string str = "123456";
            int num = str.IntegerExtension();
            Console.WriteLine("The output using extension method: {0}", num);
            Console.ReadLine();
        }
    }
}

In the above program we have used extension method IntegerExtension() to convert string to numeric type

Important points while using extension methods:
  • An extension method must be defined in a top-level static class.
  • An extension method with the same name and signature as an instance method will not be called.
  • Extension methods cannot be used to override existing methods.
  • The concept of extension methods cannot be applied to fields, properties or events.
  • Overuse of extension methods is not good style of programming.
Object Initializers:
Object Initializers let you assign values to any accessible fields or properties of an object at creation time without having to explicitly invoke a constructor.

The following example shows how to use an object initializer with a named type, Cat. Note the use of auto-implemented properties in the Cat class
 
Examples
class Cat
{
    // Auto-implemented properties.
    public int Age { get; set; }
    public string Name { get; set; }
}
 
Cat cat = new Cat { Age = 10, Name = "Fluffy" };

Object Initializers with Anonymous types:
                
var pet = new { Age = 10, Name = "Fluffy" };


Anonymous types enable the select clause in a LINQ query expression to transform objects of the original sequence into objects whose value and shape may differ from the original.
 
    var productInfos =
    from p in products
    select new { p.ProductName, p.UnitPrice };

             It is a compile-time error to use a collection initializer with a nullable struct.

Collection Initializers
  • Collection initializer gives a simple syntax to create instance of a collection.
  • Any object that is implementing System.Collections.Generic.ICollection<T>can be initialized with collection initializer.
Let us say, we have a class Student.cs

public  class Student
{
   public string FirstName { get; set; }
   public string LastName { get; set; }
}

Now if we want to make collection of this class and add items of type student in that collection and retrieve through the collection, we need to write below code


Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication16
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Student> lstStudent = new List<Student>();
            Student std = new Student();
            std.FirstName = "Dhananjay";
            std.LastName = "Kumar ";
            lstStudent.Add(std);
            std = new Student();
            std.FirstName = "Mritunjay ";
            std.LastName = "Kumar";
            lstStudent.Add(std);
            foreach (Student resstd in lstStudent)
            {
                Console.WriteLine(resstd.FirstName);
            }
            Console.Read();
        }
    }
}

Implicitly Types Local Variable:
Implicitly typed local variable can be defined with VAR keyword. The var keyword instructs the compiler to infer the type of the variable from the expression on the right side of the initialization statement.The inferred type may be a built-in type, an anonymous type, a user-defined type, or a type defined in the .NET Framework class library.
// i is compiled as an int
var i = 5;
 
// s is compiled as a string
var s = "Hello";
 
// a is compiled as int[]
var a = new[] { 0, 1, 2 };
 
// expr is compiled as IEnumerable<Customer>
// or perhaps IQueryable<Customer>
var expr =
    from c in customers
    where c.City == "London"
    select c;
 
// anon is compiled as an anonymous type
var anon = new { Name = "Terry", Age = 34 };
 
// list is compiled as List<int>                             
var list = new List<int>();

Lambda Expressions:
*       A lambda expression is an anonymous function that can contain expressions and statements, and can be used to create delegates or expression tree types.
  •  All lambda expressions use the lambda operator =>, which is read as "goes to".
  • The left side of the lambda operator specifies the input parameters (if any) and the right side holds the expression or statement block.
  • The lambda expression x => x * x is read "x goes to x times x." This expression can be assigned to a delegate type as follows:
Example:

      delegate int del(int i);
static void Main(string[] args)
{
    del myDelegate = x => x * x;
    int j = myDelegate(5); //j = 25
}
To create an expression tree type:
using System.Linq.Expressions;
 
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Expression<del> myET = x => x * x;
        }
    }
}
 
A lambda expression with an expression on the right side is called an expression lambda. Expression lambdas are used extensively in the construction of Expression Trees 
               (input parameters) => expression
 
The parentheses are optional only if the lambda has one input parameter; otherwise they are required. Two or more input parameters are separated by commas enclosed in parentheses:
               (x, y) => x == y

Sometimes it is difficult or impossible for the compiler to infer the input types. When this occurs, you can specify the types explicitly as shown in the following example:
               (int x, string s) => s.Length > x

How to: Use Lambda Expressions in a Query

Example:
class SimpleLambda
{
    static void Main()
    {
 
        // Data source.
        int[] scores = { 90, 71, 82, 93, 75, 82 };
 
        // The call to Count forces iteration of the source
        int highScoreCount = scores.Where(n => n > 80).Count();
 
        Console.WriteLine ("{0} scores are greater than 80", highScoreCount);
 
        // Outputs: 4 scores are greater than 80            
    }
}
 
The above example demonstrates how to use a lambda expression in a method-based query by using the Enumerable. Where standard query operator. 
 
Note that the Where method in this example has an input parameter of the delegate type Func(Of TResult) and that delegate takes an integer as input and returns a Boolean. 
 
The lambda expression can be converted to that delegate

Expression Trees

Expression trees represent code in a tree-like data structure, where each node is an expression, for example, a method call or a binary operation such as x < y.

Expression trees are also used in the dynamic language runtime (DLR) to provide interoperability between dynamic languages and the .NET Framework and to enable compiler writers to emit expression trees instead of Microsoft intermediate language (MSIL).

create an expression tree that represents the lambda expression num => num < 5 (C#)
 
Example:
 
Expression<Func<int, bool>> lambda = num => num < 5;

LINQ Query Expression:
  • Query expressions can be used to query and to transform data from any LINQ-enabled data source. For example, a single query can retrieve data from a SQL database, and produce an XML stream as output.
  • Query expressions are easy to master because they use many familiar C# language constructs.
  • The variables in a query expression are all strongly typed, although in many cases you do not have to provide the type explicitly because the compiler can infer it.
  • A query is not executed until you iterate over the query variable in a Foreach statement. For more information,
  • At compile time, query expressions are converted to Standard Query Operator method calls according to the rules set forth in the C# specification. Any query that can be expressed by using query syntax can also be expressed by using method syntax. However, in most cases query syntax is more readable and concise.
Examples:
class LINQQueryExpressions
{
    static void Main()
    {
 
        // Specify the data source.
        int[] scores = new int[] { 97, 92, 81, 60 };
 
        // Define the query expression.
        IEnumerable<int> scoreQuery =
            from score in scores
            where score > 80
            select score;
 
        // Execute the query.
        foreach (int i in scoreQuery)
        {
            Console.Write(i + " ");
        }            
    }
}
// Output: 97 92 81

Automatic Properties:

Previously we used to define Properties the following way.
private string name;
 
public string Name
{
    get { return name; }
    set { name = value; }
}

According to Automatic Properties we can define the properties in the following way.
 
 
public string Name
{
    get;
    set;
}

Partial Methods:

1. Partial method declarations must begin partial keyword.
2. The return type of a partial method must be void.
3. Partial methods can have ref but not out parameters.
4. Partial methods are implicitly private, and therefore they cannot be virtual.
5. Partial methods cannot be extern, because the presence of the body determines whether they are defining or implementing.

To create a partial method we create the declaration of the method in one part of the partial class and implementation in the other part of the partial class. The implementation is optional. If the implementation is not provided, then the method and all the calls to the method are removed at compile time. 

Therefore, any code in the partial class can freely use a partial method, even if the implementation is not supplied. No compile-time or run-time errors will result if the method is called but not implemented.

In summary a partial method declaration consists of two parts.

The definition, and the implementation. These may be in separate parts of a partial class, or in the same part. If there is no implementation declaration, then the compiler optimizes away both the defining declaration and all calls to the method.

Advantages of partial methods

Partial methods can be used to customize generated code. They allow for a method name and signature to be reserved, so that generated code can call the method but the developer can decide whether to implement the method. Much like partial classes, partial methods enable code created by a code generator and code created by a human developer to work together without run-time costs.

Partial Methods Example:


   public partial class CustomTypedCollection
   {
    partial void BeforeAddingElement(CustomElement element);
    
      public void AddElement(CustomElement element)
       {
        BeforeAddingElement();
       }
   }
    
 
  public partial class CustomTypedCollection
  {
    partial void BeforeAddingElement(CustomElement element)
       {
         Console.WriteLine("Element " + element + " is being added.");
       }
   }
    
 
  class Program
  {
    static void Main(string[] args)
     {
        CustomTypedCollection c = new CustomTypedCollection();
        c.AddElemeent(new CustomElement());
     }
  }

No comments :

Post a Comment