Showing posts with label IComparable interface. Show all posts
Showing posts with label IComparable interface. Show all posts

Tuesday, March 20, 2012

Implementing IComparer Interface

We discussed IComparable interface in previous post and touched a bit on IComparer interface. IComparable interface only compares two objects of the same type and the class must implement IComparable interface. But what if you have two different objects that you want to compare, or what if you want to compare the same object, but the class doesn't implement ICmparable interface?

IComparer interface provides additional methods of comparing the objects. For example, we can sort a class based on multiple properties or fields.

This interface implements a method called "Compare()" which takes two object parameters and returns an integer value like "CompareTo()" method.

Let's use the same example like we used in previous post but this time we will use "IComparer" interface.

Order Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ComparableInterface
{
    class Orders
    {
        public int orderID { get; set; }
        public DateTime orderDate { get; set; }
        public int quantity { get; set; }
        public int customerID { get; set; }
        public string customerName { get; set; }
        public Status OrderStatus { get; set; }
           

    }
}

Three classes implementing "Compare" method
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ComparableInterface
{
    class OrderCompare:IComparer<Orders>
    {
        
        //you must implement Compare method declared in IComparable interface
        //sort in ascending order
        public int Compare(Orders order1, Orders order2)
        {
            if (order1.orderID > order2.orderID) return 1;
            else if (order1.orderID < order2.orderID) return -1;
            else return 0;
        }

    }
    class OrderCompare2:IComparer<Orders>
    {
        //but you can implement overloaded signature
        //sort in descending order
        public int Compare(Orders order1, Orders order2)
        {
            if (order1.orderID < order2.orderID) return 1;
            else if (order1.orderID > order2.orderID) return -1;
            else return 0;
        }
    }
    class OrderCompare3 : IComparer<Orders>
    {
        //sort by different field - string sort
        public int Compare(Orders order1, Orders order2)
        {
            return string.Compare(order1.customerName,order2.customerName);
        }
    }
}


Using the Sort Method
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ComparableInterface
{
    class Program
    {
        
        static void Main(string[] args)
        {

            //Let's create a collection of orders and then sort them.
            List<Orders> orderlist = new List<Orders>
            {
                new Orders{orderID=100,orderDate=DateTime.Today,
                           quantity=5,customerID=10,
                           customerName="Second User",OrderStatus=Status.placed},
                new Orders{orderID=90,orderDate=DateTime.Today,
                           quantity=15,customerID=20,
                           customerName="First User",OrderStatus=Status.placed}
            };
            //let's not sort it
            foreach (Orders order in orderlist)
            { Console.WriteLine("Order ID:{0}", order.orderID); }

            Console.WriteLine(Environment.NewLine);

            //now sort using 1st comparer
            Console.WriteLine("Sort Using Order ID - Ascending");
            OrderCompare ordersort = new OrderCompare();
            orderlist.Sort(ordersort);
           foreach (Orders order in orderlist)
            { Console.WriteLine("Order ID:{0}, CustomerName{1} ", 
                                 order.orderID,order.customerName); }

           Console.WriteLine(Environment.NewLine);
           //now sort using end comparer
           Console.WriteLine("Sort Using Order ID - Descending");
           OrderCompare2 ordersort2 = new OrderCompare2();
           orderlist.Sort(ordersort2);
           foreach (Orders order in orderlist)
           { Console.WriteLine("Order ID:{0}, CustomerName{1} ", 
                                order.orderID, order.customerName); }

           Console.WriteLine(Environment.NewLine);
           //now sort using end comparer
           Console.WriteLine("Sort Using Customer Name");
           OrderCompare3 ordersort3 = new OrderCompare3();
           orderlist.Sort(ordersort3);
           foreach (Orders order in orderlist)
           { Console.WriteLine("Order ID:{0}, CustomerName{1} ", 
             order.orderID, order.customerName); }

            Console.Read();

        }
    }
}

Compare method allows you to compare two objects even if they don't implement IComparer interface. You simply pass an instance of the class implementing this interface to the Sort method.

Thank you.

Saturday, March 17, 2012

Implementing IComparable Interface

As we discussed in previous posts, an interface is a contract. A class implementing an interface must implement all the signatures that are declared in this interface.

Why do you need interfaces if all they provide are the method signatures with no actual implementation? One of the reason you implement an interface is to ensure code reuse and standards. By implementing an interface, you can be virtually guaranteed that a class implementing an interface must have implemented its signatures.

For example, suppose you have a car class and a truck class, both implementing an interface IAutoMobile. IAutoMobile has a signature method called "Horsepower". Since both car and truck classes implement IAutomobile, you can be sure both classes will also implement "Horsepower" method.You can write a static method that can accept an object of type IAutoMobile and call the "Horsepower" method. Depending on the object type you passed to this method (class or truck), the code will execute the appropriate "Horsepower" and return you the information.

To see an example of this, see my previous post titled Abstraction via Interfaces - II.

While you can create and implement your own interfaces, .NET provides several interfaces that you can implement  in your classes. Today, we will discuss one such interface "IComparable".

IComparable interface provides a "CompareTo" signature that you can implement in a class to compare the two objects of this type.

Let's consider an example...

Orders Class implementing IComparable
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ComparableInterface
{
    class Orders : IComparable
    {
        public int orderID { get; set; }
        public DateTime orderDate { get; set; }
        public int quantity { get; set; }
        public int customerID { get; set; }
        public Status OrderStatus { get; set; }

        //you must implement CompareTo method declared in IComparable interface

        public int CompareTo(object obj)
        {
            //cast the object to its proper type
            Orders order = obj as Orders;
            //OR
            //Orders order = (Orders)obj;
            
            if (this.orderID > order.orderID) return 1;
            else if (this.orderID < order.orderID) return -1;
            else return 0;
        }
        
    }
}


Main Method
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ComparableInterface
{
    class Program
    {
        static void Main(string[] args)
        {

            //Let's create a collection of orders and then sort them.
            List<Orders> orderlist = new List<Orders>
            {
                new Orders{orderID=100,orderDate=DateTime.Today,quantity=5,
                           customerID=10,OrderStatus=Status.placed},
                new Orders{orderID=90,orderDate=DateTime.Today,quantity=15,
                           customerID=20,OrderStatus=Status.placed}
            };
            //let's not sort it
            foreach (Orders order in orderlist)
            { Console.WriteLine("Order ID:{0}", order.orderID); }

            Console.WriteLine(Environment.NewLine);
            //now sort it
            orderlist.Sort();
            foreach (Orders order in orderlist)
            { Console.WriteLine("Order ID:{0}", order.orderID); }

            Console.Read();

         }
    }
}

Let's review the output before and after the sort. If you look closely, the output before orderlist.Sort() method is in the order objects were added to the collection, but after the Sort(), the objects are listed in ascending order based on the order ID. You may be wondering how come we didn't call the CompareTo method? Actually a Sort() method internally uses CompareTo method to compare the objects based on your implementation. Try the same example but without implementing IComparable interface and you will receive an error.

Output



The CompareTo method in the above example takes a generic object which then must be cast into a specific type. Framework provides another type safe interface "IComparable<>" which you can implement in your classes and no typecasting will be necessary.

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

namespace ComparableInterface
{
    class Orders2 : IComparable<Orders2>
    {
        public int orderID { get; set; }
        public DateTime orderDate { get; set; }
        public int quantity { get; set; }
        public int customerID { get; set; }
        public Status OrderStatus { get; set; }

        //you must implement CompareTo method declared in IComparable interface

        public int CompareTo(Orders2 order)
        {
            //not casting necessary

            if (this.orderID > order.orderID) return 1;
            else if (this.orderID < order.orderID) return -1;
            else return 0;
        }
    }
}


IComparable is useful when a class implements this interface and you are comparing the same objects. CompareTo method takes another object which is of the same type and compares the current object to the passed one. But what if your class doesn't implement IComparable or if you want to compare two different objects. Framework provides another interface called IComparer. This interface defines a Compare() method that can take two objects of another type and compares them. We will look at an example of the ICompare interface in future post.

Thank you.