menu

Sunday, October 9, 2016

Sorting List by IComparable vs IComparer

List<T> class has a Sort() method which sorts the elements in the entire List<T> using the default comparer. (<T> => , ...)

List<string> strList = new List<string>();
strList.Add("Ss");
strList.Add("As");
strList.Add("Rs");
strList.Add("Ks");
strList.Sort();
foreach (string item in strList)
{
    Console.WriteLine(item);
}

IComparable - Sorting list of complex type like List<Employee> using IComparable and only by one way.

public class Employee
{
    public string Name { getset; }
    public int Age { getset; }
}

List<Employee> employee = new List<Employee>();
employee.Add(new Employee() { Name = "Ss", Age = 30 });
employee.Add(new Employee() { Name = "As", Age = 25 });
employee.Add(new Employee() { Name = "Rs", Age = 20 });
employee.Add(new Employee() { Name = "Ks", Age = 30 });
employee.Add(new Employee() { Name = "Av", Age = 50 });
employee.Sort();
foreach (Employee item in employee)
{
    Console.WriteLine("{0}, {1}", item.Name, item.Age);
}

So in order to do this we will have to implement Employee class by IComparable. and have to put sorting logic in implemented function CompareTo.

public class Employee : IComparable<Employee>
{
    public string Name { get; set; }
    public int Age { get; set; }
    public int CompareTo(Employee other)
    {
        if (this.Age == other.Age)
        {
            return this.Name.CompareTo(other.Name);
        }
        return this.Age.CompareTo(other.Age);
    }
}

IComparer - Used to sorting list of complex type using IComparer and by multiple ways like Name or by Age.

public class Employee
{
    public string Name { get; set; }
    public int Age { get; set; }
}
public class SortEmployeeByName : IComparer<Employee>
{
    public int Compare(Employee x, Employee y)
    {
        return string.Compare(x.Name, y.Name);
    }
}
public class SortEmployeeByAge : IComparer<Employee>
{
    public int Compare(Employee x, Employee y)
    {
        if (x.Age == x.Age)
        {
            return 0;
        }
        if (x.Age > y.Age)
        {
            return 1;
        }
        if (x.Age < y.Age)
        {
            return -1;
        }
        return 0;
    }
}

List<Employee> employee = new List<Employee>();
employee.Add(new Employee() { Name = "Ss", Age = 35 });
employee.Add(new Employee() { Name = "As", Age = 25 });
employee.Add(new Employee() { Name = "Rs", Age = 20 });
employee.Add(new Employee() { Name = "Ks", Age = 30 });
employee.Add(new Employee() { Name = "Av", Age = 50 });
//---------------
Console.WriteLine("By Name ....");
employee.Sort(new SortEmployeeByName());
foreach (Employee item in employee)
{
    Console.WriteLine("{0}, {1}", item.Name, item.Age);
}
//---------------
Console.WriteLine("By Age ....");
employee.Sort(new SortEmployeeByAge());
foreach (Employee item in employee)
{
    Console.WriteLine("{0}, {1}", item.Name, item.Age);
}



Signing - Strong vs Weak Reference

Prerequisite - Create 2 solution first one (Solution1) with 2 project (console - ConsoleApp and class library - CLApp) another (Solution2) with one project (class library - CLApp).
Create a class with same name (say MyClass) and function (say MyFun) in both class library and print message like "Test1" and "Test1" respectively. Now in Solution1 add the reference of class library to console app and inside main function call MyClass.MyFun(), build and copy ConsoleApp.exe and CLApp.dll in a new folder and run the ConsoleApp.exe and verify the output (Test1) on console.

Problem - Build Solution2 and copy the CLApp.dll to newly created folder and replace the old CLApp.dll of Solution1. Run the ConsoleApp.exe and verify the output (Test2) on console. The problem here is that ConsoleApp.exe is not strongly referenced with CLApp.dll and this is not safe at all because at anytime one who know about the class and function can change its internal logic and that will replace its behaviour. This is because of weak reference.

Solution - Go to property of class library project in Solution1 and sign in with a MyTest.snk file

and then refer it to console app (this will be a strong reference) and follow the same procedure of replacing the dll of Solution2 and run the app. This time it will throw exception saying that ...
Unhandled Exception: System.IO.FileLoadException: Could not load file or assembly 'Signing-StrongAndWeakReferenceDLL, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9498fd7f75415bf8' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT:0x80131040) at Signing_StrongAndWeakReference.Program.Main(String[] args)