Tuesday, February 28, 2012

Generic Collections

In previous post we talked about Arrays and a special collection object called an ArrayList. We also saw some of the benefits and drawbacks of each approach. Today we will talk about generic collections and how you can use them to create a collection of a specific type and add objects of that particular type to this collection.

We will also talk about how you can pass a collection of any type to a generic method and then inspect the type and do something with it.

Generic Collections
Lets assume you have the following class...

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

namespace GenericsTest
{
    public class Sales
    {
        private string _salesAssociate;
        private double _projected;
        private double _actual;

        public String SalesAssociate
        {
            get { return _salesAssociate; }
            set { _salesAssociate = value; }
        }
        public double Projected
        {
            get { return _projected; }
            set { _projected = value; }
        }
        public double Actual
        {
            get { return _actual; }
            set { _actual = value; }
        }
    }
}

Let's create another class...

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

namespace GenericsTest
{
    public class Salary
    {
        private string _salesAssociate;
        private double _baseSalary;
        private double _commission;

        public String SalesAssociate
        {
            get { return _salesAssociate; }
            set { _salesAssociate = value; }
        }
        public double BaseSalary
        {
            get { return _baseSalary; }
            set { _baseSalary = value; }
        }
        public double Commission
        {
            get { return _commission; }
            set { _commission= value; }
        }
    }
}

Let's build a collection of these objects. We will create two generic collections - each of specific type i.e. Sales and Salary. Notice, that since the collection is of specific type, you cannot mix and match the objects. Although there are ways to do that, but we will cover it in future posts.

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

namespace GenericsTest
{
    class Program
    {
        static void Main(string[] args)
        {
            //declare generic list of type sales
            List<Sales> lstSales = new List<Sales>();
            List<Salary> lstSalary = new List<Salary>();

           //lets add few objects to these collections
            Sales oSales = new Sales();
            oSales.SalesAssociate = "Mike Smith";
            oSales.Projected = 1000;
            oSales.Actual = 1150;
            //Add to collection
           lstSales.Add(oSales);

           //add another object
            Sales oSales1 = new Sales();
            oSales1.SalesAssociate = "Patty Smith";
             oSales1.Projected = 1200;
            oSales1.Actual = 1350;
            //Add to collection
            lstSales.Add(oSales);

           //lets add few objects to another collection
            Salary oSalary = new Salary();
            oSalary.SalesAssociate = "Mike Smith";
            oSalary.BaseSalary= 500;
            oSalary.Commission= 200;
            //Add to collection
           lstSalary.Add(oSalary);

           //add another object
            Salary oSalary1 = new Salary();
            oSalary1.SalesAssociate = "Patty Smith";
            oSalary1.BaseSalary= 500;
            oSalary1.Commission= 275;
            //Add to collection
           lstSalary.Add(oSalary1);
    
       }
    }
}
          


What if you want to use the same method to pass these collections and do something based on its type. Since every object in .NET inherits from System.Object, you can pass them as object type, but instead we will do something better here.

Let's create yet another class which will do something with these two objects defined above.

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

namespace GenericsTest
{
    public static class DataType
    {
        
        public void DoSomething<T>(List<T> lstData)
        {
           
        if (lstData.GetType() == typeof(List<Sales>))
         {

         for (int i = 0; i < lstData.Count; i++)
         {
        Sales oSale = (Sales)Convert.ChangeType(lstData[i], typeof(Sales));
        Console.WriteLine(String.Format("Sales Associate:{0},Projected Sales:{1},
        Actual Sales:{2}",oSale.SalesAssociate, oSale.Projected,oSale.Actual));                   
        Console.WriteLine(Environment.NewLine);            
         }
       }
       if (lstData.GetType() == typeof(List<Salary>))
       {

       for (int i = 0; i < lstData.Count; i++)
       {
        Salary oSalary = (Salary)Convert.ChangeType(lstData[i], typeof(Salary));
        Console.WriteLine(String.Format("Sales Associate:{0},Salary:{1},
        Commission:{2}",oSalary.SalesAssociate, 
        oSalary.BaseSalary,oSalary.Commission));              
        Console.WriteLine(Environment.NewLine);            
        }
       }
      }
    }
  }

Now all you have to do is pass either collection to this method. You can extend this method to accept collection of other types, like this...

DataType.DoSomething(lstSales);
//or
DataType.DoSomething(lstSalary);     


Generics is a very powerful concept which allows for better and more flexible code. Generics, along with reflection which we covered earlier can be a powerful tool.

Thank you.


No comments:

Post a Comment