• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 246
  • Last Modified:

Generics Sample

Hi,

I read on Generics but could not get the concept since most of the examples involved are on numbers etc. Can someone give me an example on generics using very simple example with sample say using Employees, Salaries, or items/orders etc. Such day to day example will help me get the concept.

Regards,
MI
0
vj_mi
Asked:
vj_mi
2 Solutions
 
icrCommented:
In terms of using generics, I will show an example using the List<T> class that comes with .NET 2.0:

List<Employee> employeesList = new List<Employee>();
employeesList.Add(new Employee("Mark"));
employeesList.Add(new Employee("Sarah"));
Employee tempEmployee = new Employee("Tony the Temp");
employeesList.Add(tempEmployee);
employeesList.Add(new Employee("Jane"));
employeesList.Remove(tempEmployee);
employeesList.Add(new DateTime("10/20/2009")); // Will throw an exception because it is not an Employee object.

We have created a list of Employee's that is strongly typed - that is we can only add and remove Employee objects (notice when we tried to add a DateTime object instead it threw an exception). Normally we would have to create a new class for each type of list we wanted - a class that took Employee's and had an add method like this:

public class EmployeeList
{
      ...
      public void Add(Employee employee)
      {
            ...
      }
      ...
}

and another if we wanted a list for, say, Animals:

public class AnimalsList
{
      ...
      public void Add(Animal animal)
      {
            ...
      }
      ...
}

Now obviously lists have several things in common, two of which we have already seen - add and remove (the other big one is getting the value by index) so it is wasteful to have to re-write the code each time just because we are using a different type. This is where generics come in. We can re-write the class to look something like this (though in reality you wouldn't write this particular example yourself because the framework already has a generic list class):

public class List<T>
{
      ...
      public void Add(T item)
      {
            ...
      }
      ...
}

This basically says we have a class "List" of generic type "T", which is a given class. Anytime the compiler (actually the JITer I think, but easier to think in terms of the compiler for now) see's "T" it will replace it with the class. So if we create a new List<Employee>() our generic list class now looks like this:

public class List
{
      ...
      public void Add(Employee item)
      {
            ...
      }
      ...
}

And if we created a new List<Animal>() it would look like this:

public class List
{
      ...
      public void Add(Animal item)
      {
            ...
      }
      ...
}

Of course this is all done automatically under the covers, you don't have to re-write the definitions, that's just to show you what it is equivilent to.

Generics are usually (but not only) used when you have a data structure (e.g. list, queue, stack) that can act upon any class.

For a final example, let's take orders. You want to have a queue of orders so you can add orders to the end of the queue, and take them off the front for processing. The framework has a generic queue class, which looks a little bit like this (though this is simplified a great deal and has no range checking):

public class Queue<T>
{
      private T[] items;
      private int frontPointer;
      private int backPointer;

      private int size;
      public int Size { get { return size; } }

      public Queue(int size)
      {
          this.size = size;
          items = new T[Size];
      }

      public void Enqueue(T item)
      {
          items[backPointer] = item;
          backPointer += 1;
          if (backPointer == Size)
          {
            backPointer = 0;
          }
      }

      public T Dequeue()
      {
          T item = items[frontPointer];
          // Can't use "null" because it may be a value type (e.g. int). default(T) is null for reference types and the default
          // value for value types. Just a small implimentation detail.
          items[frontPointer] = default(T);
          frontPointer += 1;
          if (frontPointer == Size)
          {
            frontPointer = 0;
          }
          return item;
      }
}
   
So you could then do:

Queue<Order> orders = new Queue<Order>(20);
orders.Enqueue(new Order("Paper", 2));
orders.Enqueue(new Order("Staples", 4));
orders.Enqueue(new Order("Pens", 20));
Order nextOrder = orders.Dequeue();

Then, if we ever need a queue for anything else we don't have to re-write a new specific one just for that class, we can re-use our generic Queue:

Queue<int> numbers = new Queue<int>(20);
Queue<string> strings = new Queue<string>(20);
Queue<PrinterJob> jobs = new Queue<PrinterJob>(15);
0
 
JimBrandleyCommented:
First, icr - That was a very nice description, clear, thorough and easy to understand!

There are just a few things I would add.
1. The iterator supplied by the base List class can be used in a foreach loop. For example,
List<Employee> allEmployees = new List<Employee>(200);

// Then add some employees...

foreach(Employee thisEmp in allEmployees)
{
   // do something with this employee
}

And, you can derive your own class from List<T> to add behavior. For example:
public class EmployeeList : List<Employee>
{
   public Employee GetSupervisor( Employee thisEmployee )
   {
      // Find the employee in the list, then locate the supervisor and return that entry
   }
   public EmployeeList GetDepartmentList( string departmentName )
   {
      // Find all employees in the specified department and return a new list containing only those employees
   }
}


Jim
0

Featured Post

Never miss a deadline with monday.com

The revolutionary project management tool is here!   Plan visually with a single glance and make sure your projects get done.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now