.Net Articles

What's new in C# 3.0

In this article, I will cover at a glance the new features of C# 3.0. I have been working with this new development environment for several days and want to share my experience with you
  1. Implicit typed local variables

    Local variables can be declared as type var, whose actual type of the variable is determined by the compiler based on the data schema (see Listing 1). It's mainly used to store anonymous types in LINQ.
            
    Listing 1
     
    Public Class Customer
        {
            public string Fullname
            { get; set; }
            public string ContactAddress
            { get; set; }
        }

    Listing 2
     
    Customer objCustomer = new Customer();
    objCustomer.Fullname = "John";
    objCustomer.ContactAddress = "My address";

    Listing 3

    Object Initializers allow you to re-write the previous code in a concise way (see Listing 4). 
     
    Customer objCustomer = new Customer { Fullname="John", ContactAddress="My address"};  
    Listing 4
     
    List<Customer> objCustomerList = new List<Customer>
                {
                    new Customer{Fullname="John Olamendy", ContactAddress="Address1"},
                    new Customer{Fullname="Mary Perez", ContactAddress="Address2"},
                    new Customer{Fullname="Anthony Frances", ContactAddress="Address3"}
                };

    Listing 5
     
    public static class CheckString
    {
          public static bool MyExtensionMethod_IsEmpty(this string value)
          {
                bool bResult = true;
     
                if (value != null && !value.Equals(""))
                {
                    bResult = false;
                }
     
                return bResult;
          }
    }
    Listing 6

    Now let's use the extension method in a scenario (see Listing 7). 
    string strCustomerName = "John C. Olamendy";
    if (strCustomerName.MyExtensionMethod_IsEmpty())
    {
        System.Console.WriteLine("The string is empty");
    }
    else
    {
        System.Console.WriteLine("The string is is not empty");
    } 
    Listing 7

    One common built-in extension shipped in Microsoft.NET is inside the namespace System.Linq and allows easy querying of the data by using Linq query operators. Let's suppose we want to query the list of customer already defined  (objCustomerList) in order to get customers whose names begins with the letter J. You need to use the Where extension method provided by System.Linq to retrieve the result set (see Listing 8). 
    IEnumerable<Customer> rsCustomer = objCustomerList.Where(p => p.Fullname.StartsWith("J"));

    Listing 8

    The statement for the query is written using the principles of "Lambda expression", which is a natural evolution of anonymous methods.
     
    var objProduct = new { ProductID=1, Name="My Product", UnitPrice=10.2};
    System.Console.WriteLine("The product info is: Id={0}, Name={1}, UnitPrice={2}", objProduct.ProductID, objProduct.Name, objProduct.UnitPrice);
     
    Listing 9

    One common scenario where we can use Anonymous Type is when we want to query and work with data using LINQ expressions, and we want to define the schema of the result set in-line. Let's suppose that we want to query a database in order to search for products that satisfy some conditions such as UnitPrice great than a value in order to have an insight of expensive products (see Listing 10). This syntax allows using the dynamic language flexibility without losing the strong-type language support for compile-time checking and intellisense in Visual Studio.
     
    var rsProduct = from p in db.Products
                    where p.UnitPrice > 10000.00
                    select new
                    {
                        Id = p.ProductID,
                        Name = p.Name,
                        Price = p.UnitPrice
                    };
     
    foreach (var objProduct in rsProduct)
    {
        System.Console.WriteLine("Expensive products. ID={0}, Name={1}, Price={2}", objProduct.Id, objProduct.Name, objProduct.Price); 
    }

    Listing 10

     
    IEnumerable<Customer> rsCustomer = objCustomerList.Where(p => p.Fullname == "John Olamendy");

    Listing 11

    This expression is semantically equivalent to anonymous methods following the rule params=>expression. That is, the p is parameter of the anonymous method referencing to every instance of Customer in the collection. In this case, we don't need to declare the parameter type because it's inferred by the compiler from the types in the collections. The expression is normal C# statement that, in this case, returns a Boolean value. Let's re-write the previous lambda expression into an anonymous method (see Listing 12).
     
    IEnumerable<Customer> rsCustomer = objCustomerList.Where
    (
       delegate(Customer objTemp)
       {
         return objTemp.Fullname == "John Olamendy";
       }
    ); 
    Listing 12

    I would like to illustrate the evolution from delegates (in early C# language), through anonymous methods (in C# 2.0) to lambda expression (in C# 3.0) using an example taking from the Visual Stduio 2008 documentation (see Listing 13).

     
        delegate void TestDelegate(string s);
        static void M(string s)
        {
            Console.WriteLine(s);
        }
     
        static void Main(string[] args)
        {
            // Original delegate syntax required
            // initialization with a named method.
            TestDelegate testdelA = new TestDelegate(M);
     
            // C# 2.0: A delegate can be initialized with
            // inline code, called an "anonymous method." This
            // method takes a string as an input parameter.
            TestDelegate testDelB = delegate(string s) { Console.WriteLine(s); };
     
            // C# 3.0. A delegate can be initialized with
            // a lambda expression. The lambda also takes a string
            // as an input parameter (x). The type of x is inferred by the compiler.
            TestDelegate testDelC = (x) => { Console.WriteLine(x); };
     
            // Invoke the delegates.
            testdelA("Hello. My name is M and I write lines.");
            testDelB("That's nothing. I'm anonymous and ");
            testDelC("I'm a famous author.");
     
            // Keep console window open in debug mode.
            Console.WriteLine("Press any key to exit.");
            Console.ReadKey();
        }
    }
    /* Output:
        Hello. My name is M and I write lines.
        That's nothing. I'm anonymous and
        I'm a famous author.
        Press any key to exit.
     */ 
    Listing 13
    class Test
    {
            // This is an integer
            var nId = 1234567;
            //This is a string
            var strFullname = "John Charles Olamendy Turruellas";
  2. Automatic properties

    Sometimes when you are implementing the logic associated with classes, you need to write the getters/setters of our properties. Properties are best practices to support the encapsulation concept in the Object-Oriented Programming paradigm. C# compiler provides an elegant way to make your code more robust using properties called automatic properties. It allows you to avoid having to manually declare a private field and write the underlying getter/setter logic. The compiler does the work for you (see Listing 2).
       
  3. Object Initializers
    When you create an instance of the business entity Customer, you write the code to call the class constructor and set the properties of the instance (Listing 3).
     
  4. Collection Initializers

    Object Initializers is a great feature to write code efficiently. C# also adds a feature to initialize collections of objects called Collection Initializers following the same concepts of Object Initializers (see Listing 5).
               
  5. Extension methods allow developers to add new methods to existing CLR types without subclassing and recompiling the original class. You can realize by defining a static class with a static method containing the extension method. You need to use the keyword this before the CLR type you want to extend. To use the new defined extension, you need to use the import keyword to import the namespace containing the extension class.

    Let's define an extension method to check whether a given string object is empty or not (see Listing 6).

     
  6. Anonymous Type is a way to encapsulate properties of an object without defining the underlying class at runtime. The type name and properties are inferred by the compiler (Listing 9).
     
  7. Lambda expression is an evolution of delegates in order to write in-line anonymous blocks in C#. It's very helpful when writing Linq query expressions by defining wrapping methods that can be passed as arguments to the evaluations. As illustrative purposes, we're going to query the list of customer (objCustomerList) defined before. This collection has new extension methods such as Where and Average which can be used along with Lambda expressions to query the array of entities.

    Let's suppose that we want to retrieve information for a particular customer; then we write the C# code along with Lambda expression as a filter as shown (see Listing 11).
     

 

2/13/2008 10:26:00 PM Published by FengLiN Category C Sharp(C#) Comments 0 Views (848)
Name

Web site

Are you human? Enter the verify code below.

Comment