Translate

Monday, January 14, 2013

Introduction to lambda C# (Lambda expression tutorial))

What is a Lambda ?

Lambda expression can be thought of a shorthand way of writing a function to assign it to a delegate. (Lamda functions return delegates)

For example what is shown below

namespace Lambda
{
    internal class Program
    {
        public delegate int ProductDelegate(int a, int b);
        private static void Main(string[] args)
        {
            var test = new Test();
            ProductDelegate productDelegate = test.Multiplier;
            var product = productDelegate(2, 3);
        } 
    }

    public class Test
    {
        public int Multiplier(int a, int b)
        {
            return a * b;
        }
    }

}

can be replaced by

namespace Lambda
{
    internal class Program
    {
        public delegate int ProductDelegate(int a, int b);
        private static void Main(string[] args)
        {
            ProductDelegate productDelegate = (x,y)=>(x*y);//read as x y goes to x*y
            var product = productDelegate(2, 3);
        }
    }
}

The compiler infers the type of input parameters x,y and the return type of x*y from the definition of the delegate it is assigned to.


Here is another example that shows the syntax of anonymous methods and lambda expression one after another, for comparison

using System;

namespace Lambda
{
    class Program
    {

        delegate int AddDelegate(int a, int b);

        static void Main(string[] args)
        {
            AddDelegate addDelegate;

            addDelegate = Add;//Assign a method to the delegate
            Console.WriteLine(addDelegate(1,2));// Displays 3

            addDelegate = delegate(int a, int b) { return (a + b); };//Assign an anonymous method to a delegate
            Console.WriteLine(addDelegate(11, 9));// Displays 20

            addDelegate = (a, b) => (a + b);//Assign a lambda expression to a delegate
            Console.WriteLine(addDelegate(10, 5));// Displays 15

        }

        public static int Add(int a,int b)
        {
            return (a + b);
        }

    }

}


How to write multiline Lambda Functions ?


using System;
 
internal class Test
{
    public delegate void PrintArray(int[] arr);
 
    private static void Main()
    {
        int[] array = {1, 2, 3};
 
        PrintArray printArray = x =>
        {
            foreach (int i in x)
            {
                Console.WriteLine(i);
            }
        };
 
        printArray(array); //displays 1 2 3
    }
}

LINQ select distinct not working (LINQ select distinct does not work)

LINQ select distinct works as expected if you are returning a List of anonymous types or a List of a primitive type. But it seems not to work if you are returning a List of a class. The way to fix that is to implement IEqualitycomparer<T> interface and pass in an instance of that implementation to the the Distinct method.  Its easier to understand this with a simple example.

The aim in the code below is to differentiate people based on their Social Security Number.

Code where select distinct does not work

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace IEqualityComparer

{
    class Program
    {
        static void Main(string[] args)
        {
 
            var people = new List<Person>();
 
            people.Add(new Person { SocialSecurityNumber = "A", Name = "Pam" });
            people.Add(new Person { SocialSecurityNumber = "B", Name = "John" });
            people.Add(new Person { SocialSecurityNumber = "C", Name = "Susan" });
            people.Add(new Person { SocialSecurityNumber = "D", Name = "Tom" });
            people.Add(new Person { SocialSecurityNumber = "A", Name = "Pam" });//THIS RECORD IS REPEATED
 
            var distinctPeople = (from p in people select p).Distinct();
 
            foreach (var person in distinctPeople)
            {
                Console.WriteLine(person.Name);//PAM GETS PRINTED TWICE, HENCE SELECT DISTINCT DOESNOT WORK
            }
 
        }
    }
 
    public class Person
    {
        public string SocialSecurityNumber { getset; }
        public string Name { getset; }
 
    }
}

Output:
Pam
John
Susan
Tom
Pam
Press any key to continue . . .




Code where select distinct works

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace IEqualityComparer
{
    class Program
    {
        static void Main(string[] args)
        {
 
            var people = new List<Person>();
 
            people.Add(new Person { SocialSecurityNumber = "A", Name = "Pam" });
            people.Add(new Person { SocialSecurityNumber = "B", Name = "John" });
            people.Add(new Person { SocialSecurityNumber = "C", Name = "Susan" });
            people.Add(new Person { SocialSecurityNumber = "D", Name = "Tom" });
            people.Add(new Person { SocialSecurityNumber = "A", Name = "Pam" });
 
            var distinctPeople = (from p in people select p).Distinct(new PersonComparer());//Note that an implementation of IEqualityComparer<Person> is passed in
 
            foreach (var person in distinctPeople)
            {
                Console.WriteLine(person.Name); 
            }
 
        }
    }
 
    public class Person
    {
        public string SocialSecurityNumber { getset; }
        public string Name { getset; }
 
    }
 
    public class PersonComparer : IEqualityComparer<Person>
    {
 
 
        public bool Equals(Person left, Person right)
        {
            if ((object)left == null && (object)right == null)
            {
                return true;
            }
            if ((object)left == null || (object)right == null)
            {
                return false;
            }
            return left.SocialSecurityNumber == right.SocialSecurityNumber;
        }
 
        public int GetHashCode(Person obj)
        {
            return obj.SocialSecurityNumber.GetHashCode();
        }
 
    }
}
Output:

Pam
John
Susan
Tom

Press any key to continue . . .

Sunday, January 13, 2013

c# Generics type constraints tutorial

When you declare a generic method or a class there are 5 types of constraints that you can put on the generic type. I demonstrate all 5 with examples

1> T should be a reference type
Example:

class Person<T> where T:class
{

}


2>  T should be a value type
Example:

class Person<T> where T:struct
{

}

3>  T should have a public parameterless constructor.
Example


class Person<T> where T:new( )
{

}

This means you can call new on T without any parameters.

var x=new T( );

4>  T should inherit from a particular class or interface
Example

class Person<T> where T : StreamReader,IEnumerable
{


}


This means T should inherit from the StreamReader class and implement IEnumerable interface

5>Where T should inherit from another generic type

class Person<T1,T2> where T1 :T2
{


}

In my personal experience, the 4th constraint is the constraint that is used most often.

C# Hashtable vs Dictionary vs Array vs ArrayList vs List search performance comparison

In this experiment I add these 5 people


Name = "Tom", Age = 32
Name = "John", Age = 22
Name = "Sandra", Age = 36
Name = "Julie", Age = 54
Name = "Samantha", Age = 21

into
1>A Hashtable,
2>A Dictionary<TKey, TValue>,
3>An Array,
4>An ArrayList and
5>A List<T>.

Then I try to find Samantha's age multiple times (Note that Samantha is the last entry) in each of these collections. These were the times taken.

Rank
Class
Time taken for the searches
1
Dictionary
 2.82 seconds
2
Hashtable
 2.96  seconds
3
Array
 4.68 seconds
4
List
 15.75 seconds
5
ArrayList
 30.08 seconds





Given below is the code used for the experiment


using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace DictionaryPerformanceComparison
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            const int searchCount = 99999999;
            DateTime begin;
            DateTime end;

            /*Create a hash table*/
            var hashTable = new Hashtable { { "Tom", 32 }, { "John", 22 }, { "Sandra", 36 }, { "Julie", 54 }, { "Samantha", 21 } };

            /*Create a dictionary*/
            var dict = new Dictionary<string, int>
                {
                    {"Tom", 32},
                    {"John", 22},
                    {"Sandra", 36},
                    {"Julie", 54},
                    {"Samantha", 21}
                };


            /*Create an array*/
            var pArray = new Person[5];
            pArray[0] = new Person { Name = "Tom", Age = 32 };
            pArray[1] = new Person { Name = "John", Age = 22 };
            pArray[2] = new Person { Name = "Sandra", Age = 36 };
            pArray[3] = new Person { Name = "Julie", Age = 54 };
            pArray[4] = new Person { Name = "Samantha", Age = 21 };


            /*Create an arraylist */
            var arLst = new ArrayList
                {
                    new Person {Name = "Tom", Age = 32},
                    new Person {Name = "John", Age = 22},
                    new Person {Name = "Sandra", Age = 36},
                    new Person {Name = "Julie", Age = 54},
                    new Person {Name = "Samantha", Age = 21}
                };


            /*Create a List*/
            var li = new List<Person>
                {
                    new Person {Name = "Tom", Age = 32},
                    new Person {Name = "John", Age = 22},
                    new Person {Name = "Sandra", Age = 36},
                    new Person {Name = "Julie", Age = 54},
                    new Person {Name = "Samantha", Age = 21}
                };


            begin = DateTime.Now;
            for (int i = 0; i < searchCount; i++)
            {
                int x = (int)hashTable["Samantha"];
            }
            end = DateTime.Now;
            Console.WriteLine("Hash table search took {0} seconds", end.Subtract(begin).TotalSeconds);


            begin = DateTime.Now;
            for (int i = 0; i < searchCount; i++)
            {
                int x = dict["Samantha"];
            }
            end = DateTime.Now;
            Console.WriteLine("Dictionary search took {0} seconds", end.Subtract(begin).TotalSeconds);


            begin = DateTime.Now;
            for (int i = 0; i < searchCount; i++)
            {
                int length = pArray.Length;
                for (int j = 0; j < length; j++)
                {
                    if (pArray[j].Name == "Samantha")
                    {
                        int age = pArray[j].Age;

                    }
                }
            }
            end = DateTime.Now;
            Console.WriteLine("Array search took {0} seconds", end.Subtract(begin).TotalSeconds);


            begin = DateTime.Now;
            for (int i = 0; i < searchCount; i++)
            {
                int x = arLst.OfType<Person>().FirstOrDefault(p => p.Name == "Samantha").Age;
            }
            end = DateTime.Now;
            Console.WriteLine("ArrayList search took {0} seconds", end.Subtract(begin).TotalSeconds);


            begin = DateTime.Now;
            for (int i = 0; i < searchCount; i++)
            {
                int x = li.FirstOrDefault(p => p.Name == "Samantha").Age;
            }
            end = DateTime.Now;
            Console.WriteLine("List search took {0} seconds", end.Subtract(begin).TotalSeconds);
        }
    }

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

}