Pages

Search

Monday, April 9, 2012

Optional and Named Parameters – C#


Visual studio 2010 C#, has extended the capability of calling a function with its argument based on name and also can omit the optional parameters which are set with default value in the function declaration.
Below example demonstrates the same.
Program.cs
  class Program
    {
        static void Main(string[] args)
        {
            try
            {
                //calling the function normally
                Console.WriteLine(CaculateArea(10, 20, "Rectangle 1"));

                //calling the function providing only "length" as named parameter and others will be default
                //which are optional
                Console.WriteLine(CaculateArea(length: 100));

                //calling the function sending all the arguments as named parameters whose order need
                //not be same as arguments order in the calling function.
                Console.WriteLine(CaculateArea(name: "Rectangle 2", width: 100, length: 200));
            }
            catch (Exception exp)
            {
                Console.WriteLine("Error : " + exp.Message);
            }
            Console.Read();
        }

        //function which width and name with default values which are like optional parameters.
        //optional parameters should always be declared at the end after the actual parametes.
        static string CaculateArea(int length, int width = default(int), string name = "No Name")
        {
            return string.Format("The area of \"{0}\" is {1}", name, length * width);
        }
    }

Output:



Partial Class and Method


Declaring a class as “partial” enables the developer to extend the capabilities of class to add extra members with in by creating the same partial class in an another file.

Ex:-
I can create below class in “Class1.cs”
  public partial class Class1
    {
        public void Method1()
        {
            Console.WriteLine("Hello this is method1");
        }
    }
I can also create a class with same name (Class1) as below, in “Class2.cs”, which means I am trying to add functions to an existing partial class.
  public partial class Class1
    {
        public void Method2()
        {
            Console.WriteLine("Hello this is method2");
        }
    }
Similarly, partial methods can be declared in a partial class and can be implemented in the specific partial class. Below example demonstrates the same.

Program.cs
    public partial class MyClass1
    {
        public void Met1()
        {
            Console.WriteLine("Method 1");
            Met2();
        }
         partial void Met2();
    }

MyClass.cs

  public partial class MyClass1
    {
        partial void Met2()
        {
            Console.WriteLine("Method 2");
        }
    }

Now when I create instance for “MyClass1” and invoke “Met1”, “Met1” when calls “Met2” it calls the implemented function in specific partial class.
Note: Partial methods cannot be declared with access specifiers and also cannot be invoked from the object of the class directly which in turn can be called in an another function(s).



Friday, April 6, 2012

Using Linq, Lamda and Indexers – Example


Below example is to create a “BookStall” (Collection of books), finding books based on “BookName” or “Price” or “Author Name and Price”.
Created “Indexer” for “BookStall” class which exposes 3 properties that returns the list of books based on “BookName” or “Price” or “Author Name and Price”.
Created a delegate (delWhereClause) in “BookStall” which returns “bool” and accepts “Book”object.
So the three indexers which are meant for different filters in book collection will create lamda expression or delegate object of type (delWhereClause) and send the delegate to a generic method “GetBooks” which applies Linq for the collection and in case of “where” it invokes the delegate which is sent as argument.

Program.cs (Console Application) :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Numerics;

namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Book objBook = null;
                BookStall objBookStall = new BookStall();
                Random objRand = new Random();

                //creating 50 books and adding to book stall
                //setting random price for each book
                for (int i = 0; i < 50; i++)
                    objBookStall.Add(new Book() { Name = "B" + i, Author = "A" + i, Price = (objRand.Next(100, 120)) });

                //Considering a book, whose name is 'B4'
                objBook = objBookStall["B4"].First();

                //Getting book based on Author and Price
                objBook = objBookStall[objBook.Author, objBook.Price].First();

                //Printing the details of "B4"
                Console.WriteLine("Book Details \n " + objBook);

                Console.WriteLine(Environment.NewLine + "Books with same Price : " + objBook.Price + Environment.NewLine);

                //Getting the books which are with similar price in the book stall and printing to Console
                objBookStall[objBook.Price].ForEach((b) =>
                   Console.WriteLine("Book Details \n " + b));

            }
            catch (Exception exp)
            {
                Console.WriteLine("Error : " + exp.Message);
            }
            Console.Read();
        }
    }

    //The book class which has the attributes related to a book
    public class Book
    {
        public string Name;
        public int Price;
        public string Author;
        public override string ToString()
        {
            return ("Book Name : " + this.Name + ", Price : " + Price + ", Author : " + Author);
        }
    }

    //Bookstall class - List of Books
    public class BookStall : List<Book>
    {
        public delegate bool delWhereClause(Book argBook);

        //Getting books based on Book Name
        public List<Book> this[string BookName]
        {
            get
            {
                return GetBooks(
                    (b) =>
                    {
                        return (b.Name.Trim().ToLower() == BookName.Trim().ToLower());
                    }
                    );
            }
        }

        //Getting books based on Price
        public List<Book> this[int Price]
        {
            get
            {
                return GetBooks(
                    new delWhereClause((b) =>
                        {
                            return (b.Price == Price);
                        }
                        ));


            }
        }

        //Getting books based on Author
        public List<Book> this[string AuthorName, int Price]
        {
            get
            {
                return GetBooks(b => b.Author.Trim().ToLower() == AuthorName.Trim().ToLower() && b.Price == Price);
            }
        }

        //Getting list of books which, invoke the where claus delegate while itterating through each book
        //in the current collection
        private List<Book> GetBooks(delWhereClause argWhereClause)
        {
            return (from b in this where argWhereClause(b) select b).ToList();
        }
    }
}

Output:


Thursday, April 5, 2012

Asynchronous Models


There are different ways like Asynchronous Programming Model or Event Asynchronous Pattern or Task Asynchronous Pattern which enable the asynchronous behavior of invoking the functions.
Usually in APM (Asynchronous Programming Model), developer has to call the beinginvoke and endinvoke functions which work with delegates to support async.  
In case of EAP (Event Asynchronous Pattern which enable), usually we create async function which has suffix as “Async”. It is required to fire an event when the async operation is completed. So when the caller is invoking the async function, caller has to register to the event which gets fired after async operation is completed.
In case of TAP (Task Asynchronous Pattern), same as like EAP the methods are suffixed as “TaskAsync” or “Aysc” to make caller ease to understand. The function returns the “Task” object to the caller, to which caller can say “continuewith” or can track it self the state of async operation.
Below source demonstrates the Sync behavior, APM, EAP and TAP.
Forms.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading.Tasks;
using System.Runtime.Remoting.Messaging;
using System.Threading;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                //synchronous method behaviour
                MessageBox.Show("Synchronous : " + SumRootN(100));

                //Asynchronous Programming Model (APM)
                IAsyncResult ar = BeginSumRootN(200, null, null);
                do { } while (!ar.IsCompleted);
                MessageBox.Show("APM : " + EndSumRootN(ar));

                //Event Asynchronous Pattern (EAP)
                OnSumRootNCompleted += new SumRootNCompletedEventHandler(Form1_OnSumRootNCompleted);
                SumRootNAsync(5);

                //Task Asynchronous Pattern (TAP)
                Task<double> objSumTask = SumRootNTaskAsync(100);
                objSumTask.ContinueWith(
                    (t) =>
                    {
                        MessageBox.Show("TAP : " + t.Result);
                    }, CancellationToken.None);
            }
            catch (Exception exp)
            {
                MessageBox.Show("Error : " + exp.Message);
            }
        }


        //methhod thats gets fired when the opertaion is completed via EAP
        void Form1_OnSumRootNCompleted(object sender, SumRootNCompletedEventArgs e)
        {
            MessageBox.Show("EAP : " + e.Result);
        }

        #region SyncronousModel
        public double SumRootN(int root)
        {
            double result = 0;
            for (int i = 1; i < 1000000; i++)
            {
                result += Math.Exp(Math.Log(i) / root);
            }
            return result;
        }
        #endregion

        #region APM (Asynchornous Programming Model)
        public delegate double delSumRootN(int root);
        public IAsyncResult BeginSumRootN(int root, AsyncCallback callback, object state)
        {
            delSumRootN objDelSumRootN = new delSumRootN(SumRootN);
            return objDelSumRootN.BeginInvoke(root, callback, objDelSumRootN);
        }

        public double EndSumRootN(IAsyncResult ar)
        {
            return (ar.AsyncState as delSumRootN).EndInvoke(ar);
        }
        #endregion

        #region Using EAP (Event Asynchronous Pattern)
        public class SumRootNCompletedEventArgs : AsyncCompletedEventArgs
        {
            public double Result;

            public SumRootNCompletedEventArgs(Exception exp, bool bCanceled, object state)
                : base(exp, bCanceled, state)
            {
            }
        }

        public void SumRootNAsync(int root)
        {
            AsyncOperation objOperation = AsyncOperationManager.CreateOperation(root);
            Action<int, AsyncOperation> act = new Action<int, AsyncOperation>(BeginSumRootNAsync);
            act.BeginInvoke(root, objOperation, null, null);
        }

        public void BeginSumRootNAsync(int root, AsyncOperation oper)
        {
            double res = 0;
            SumRootNCompletedEventArgs e = null;
            try
            {
                res = SumRootN(root);
                e = new SumRootNCompletedEventArgs(null, false, root);
                e.Result = res;
            }
            catch (Exception exp)
            {
                e = new SumRootNCompletedEventArgs(exp, false, root);
            }
            oper.PostOperationCompleted(
               (o) =>
               {
                   if (OnSumRootNCompleted != null)
                       OnSumRootNCompleted(root, e);

               }, root);
        }
        public delegate void SumRootNCompletedEventHandler(object sender, SumRootNCompletedEventArgs e);
        public event SumRootNCompletedEventHandler OnSumRootNCompleted;
        #endregion

        #region TAP (Task Asynchronous Pattern)
        public Task<double> SumRootNTaskAsync(int root)
        {
            Task<double> objTask = Task.Factory.StartNew<double>(
                () => { return SumRootN(root); }, CancellationToken.None);
            return objTask;
        }
        #endregion
    }
}