Generics
Generics
In this Article I will explain about Generics Feature with some examples.
Generics
Generics are used to help make the code in the software components much more reusable. They are a type of data structurethat contains code that remains the same. The data type of the parameters can change with each use.The usage within the data structure adapts to the different data type of the passed variables. Each time the generic is used, it can be customized for different data types without needing to rewrite any of the internal code. Generics permit classes, structs, interfaces, delegates, and methods to be parameterized by the types of data they store and manipulate. We can refer to a class, where we don't force it to be related to any specific Type, but we can still perform work with it in a Type-Safe manner. An example where we could implement Generics is in dealing with collections of items (integers, strings, Orders etc.). We can create a generic collection than can handle any Type in a generic and Type-Safe manner. For example, we can have a single array class to store a list of Users or even a list of Items, and when we actually use it, we will be able to access the items in the collection directly as a list of Users or Items, and not as objects (with boxing/unboxing, casting).
Generics Implementation
Let us explore an example to understand the need for Generics and the Implementation part of it. Normally we write the Arraylistclass as:
class MyArrayList { private object[] items; private int count=0; ... public void Add(object item) { items[count++] = item; } public object GetItem(int index) { return items[index];
} }
In this code, any untyped object can be added to the list and be read. While adding an untyped object is possible in a direct manner , there has to be an explicit type conversion on a read access. The untyped declaration of the list results in two problems. y The compiler has no chance to verify the content of the list and the necessary type conversions. y Type failures will be recognized only at runtime-or maybe never recognized at all. You can solve both problems by using typed classes. The base class library provides an abstract base class, CollectionBase in the System.Collections namespace, that will enable you to create typed collections easily. You have to implement the body for the different methods and the indexer. Internally, the objects are stored in an untyped ArrayList, and calls are forwarded to this class. For reference types, this approach works very well, although a new class has to be explicitly developed for each data type. However, collections for value types created in this way are inefficient, because the data needs to be (un)boxed to be stored in the ArrayList internally. The solution for problems like this is the use of generic classes. A blueprint of the class is created just once. Instead of using a particular data type or object, a specific placeholder is added.
// Defining a Generic Class class MyArrayList { private ItemType[] items; private int count; ... public void Add(ItemType item) { items[count] = item; } public ItemType GetItem(int index) { return items[index]; }
The class MyArrayList can be specialized for any data-type which would, later in the class, be referenced using the name ItemType class MyArrayList We replaced the data type of items with ItemType. Now we can utilize MyArrayList for various types. For example, the code
MyArrayList iList = new MyArrayList();
Will create an instance of MyArrayList class that accepts and return only integers or that has replaced ItemType in class definition with int. Now we can only add and retrieve integers from iList.
static void Main() { MyArrayList iList = new MyArrayList(); iList.Add(25); int iValue2 = iList.GetItem(1); } Similarly for user defined type 'Employee' static void Main() { MyArrayList pList = new MyArrayList(); pList.Add(new Employee("John")); }
Although using Generics is type safe, you don't have type-safe access while developing the class itself. Because the type with which the generic class is used later is absolutely unknown, it's internally assumed to be object. Specific members of the data type can only be accessed after an explicit and therefore unsafe conversion. Possible failures will only be detected at run time.
Using Methods
Methods are another exciting field of use for Generics. Generic methods will allow you to pass one or more data types. An Example is given below.
public class MyClass { protected ItemType MyMethod(ItemType item)
{ return item; } }
Conclusion
Generics are very important and useful if you work, for example, with any kind of collections. Because of the backwards compatibility of ASP.NET 2.0, the existing collections couldn't be modified. Instead, a new namespace named System.Collections.Generic was created. It contains a lot of generic classes, structures, and interfaces like the following: y y y y y Dictionary List Queue SortedDictionary Stack
In the case of C#, generics are declared and type checked at compile time while instantiated at runtime just like any other object. C#Generics has the following advantages: 1. The Program becomes statically typed, so errors are discovered at compile-time. 2. No runtime casts are required and the program runs faster. 3. Primitive type values (e.g int) need not be wrapped. Hence the program is faster and uses less space.
Sorting ArrayList Containing User Defined Types:
Introduction: We all know about ArrayList and its functionlity, it is the dynamic array of the .Net Framework, where you can add, delete, search & sort objects in it. The issue we will descuss in this article is Sorting ArrayList. Define the issue: The problem is stated in MSDN in the definition of the Sort method it says: "Sorts the elements in the entire ArrayListusing the IComparable implementation of each element". which means that any object in the ArrayList that you wish to sort must implement the IComparable interface. I think most of .Net Framework implements the IComparable interface like Int32,Int16...,String,Decimal etc.... but what about our own types??!! the Classes and structures we build ourselvs?? do we still able to sort them??!!! yes we can do that, but note that those will be complex type, which mean that you have to know what is the parameter you are going to use to sort your own defined types, and this what we are going to see in the next sections.
Note: :if you tried to sort and array or an ArrayList that is containing your defined type, and this type do not implement theIComparable interface, you will get an exception. IComparable interface: By looking in the MSDN, I found the IComparable interface has only one method, CompareTo which take only one parameter of type object, which mean it can accept any type, and returns an integer which mean the following:
y y y
Less than zero if this instance is less than obj. Zero if this instance is equal to obj. Greater than zero if this instance is greater than obj.
So all we have to do when building our own type is to implement the IComparable interface example:
public class Employee : System.IComparable { //....code public int CompareTo(object obj) { //..implementation } }
Now we will see how to implement the IComparable interface. First we will create a new class called Employee. This class will contain Employee name,ID,salary & department name, at the begining we will sort the according to Employee ID then we will see how to implement a parametrized sorting, so can sort by name and salary or anything else. So let's see the Empolyee Class
class Empolyee : System.IComparable { private string m_EmpName; private string m_EmpDept; private int m_EmpID; private decimal m_EmpSalary; public Employee(int id, string name,string dept) { m_EmpID = id; m_EmpName = name; m_EmpDept = dept; m_EmpSalary = 0.0M; } public string Name { get{return m_EmpName;} set{m_EmpName=value;} } public string Department {
get{return m_EmpDept;} set{m_EmpDept=value;} } public int ID { get{return m_EmpID;} set{m_EmpID=value;} } public decimal Salary { get{return m_EmpSalary;} set{m_EmpSalary=value;} } /// /// Less than zero if this instance is less than obj. /// Zero if this instance is equal to obj. /// Greater than zero if this instance is greater than obj. /// /// /// This method uses the predefined method Int32.CompareTo /// public int CompareTo(object obj) { if(!(obj is Employee)) throw new InvalidCastException("This object is not of type Employee"); Employee emp = (Employee)obj; //no need to rewrite the code again, we have int.CompareTo ready to use return this.ID.CompareTo(emp.ID); } }
As you see in that class, it is easy to implement the IComparable interface. and also I didn't write the code myself, I used the Int32.CompareTo method, cause it is already implemented to compare integers, but if you wish you can write it yourself, it will be like this:
if(this.ID < emp.ID) return -1; else if(this.ID==emp.ID) return 0; else return 1;
That was easy wasn't it? Now when you add you Empolyees to an ArrayList, you can sort this ArrayList with no porblems, better than implement a sort algorithm to sort your own types. What is Next: Suppose you want to make several option for sorting!! like sorting by name or by salary??!! The implementation is too easy and simple, the solution I made is to create an enumiration with the values of sorting options:
Just simple switch..case statement. and before calling the ArrayList.Sort, I set the Property Employee.SortBy to the sort value option. I built a simple form that uses the Employee Class and store objects from it in the ArrayList, I'm using a combo box to select sort option, then I set the sort option and call theArrayList.Sort method
Generics are a new feature in version 2.0 of the C# language and the common language runtime (CLR). Generics introduce to the .NET Framework the concept of type parameters, which make it possible to design classes and methods that defer the specification of one or more types until the class or method is declared and instantiated by client code. For example, by using a generic type parameter T you can write a single class that other client code can use without incurring the cost or risk of runtime casts or boxing operations, as shown here:
// Declare the generic class public class GenericList<T> { void Add(T input) { } } class TestGenericList { private class ExampleClass { } static void Main() { // Declare a list of type int GenericList<int> list1 = new GenericList<int>(); // Declare a list of type string GenericList<string> list2 = new GenericList<string>(); // Declare a list of type ExampleClass GenericList<ExampleClass> list3 = new GenericList<ExampleClass>(); }
}
y y y Use generic types to maximize code reuse, type safety, and performance. The most common use of generics is to create collection classes. The .NET Framework class library contains several new generic collection classes in the System.Collections.Generic namespace. These should be used whenever possible in place of classes such as ArrayList in the System.Collections namespace. You can create your own generic interfaces, classes, methods, events and delegates. Generic classes may be constrained to enable access to methods on particular data types. Information on the types used in a generic data type may be obtained at run-time by means of reflection.
y y y