Generics Part I

When we talk about Generics first thing should come into our heads is “General Model”, But what do i mean with General Model or Generic?

Well lets assume that i want to write a simple 3 overloaded methods each one of these methods take an array as an argument and display the array elements separated by commas, But first method takes a string array as an argument, Second method takes an int array, And third takes double array … Well we will do thing using Overloading methods and everything will be fine right ?? Let’s check it

static void Main(string[] args)
{
int[] intarray = { 1, 2, 3, 4, 5, 6, 7 };
double[] doublearray = { 1.12, 2.58, 3.65, 4.29, 5.78 };
string[] stringarray = { “Ibrahim”, “Zeyad”, “Emad”, “Nader”, “Amr” };
Disp(intarray);
Console.WriteLine();
Disp(doublearray);
Console.WriteLine();
Disp(stringarray);
}

public static void Disp(int[] x)
{
foreach (int element in x)
Console.Write(element +”, “);
}

public static void Disp(double[] x)
{
foreach (double element in x)
Console.Write(element + “, “);
}

public static void Disp(string[] x)
{
foreach (string element in x)
Console.Write(element + “, “);
}

In the previous example we created 3 arrays of types (int, double, string) and we created method Disp to display the array elements separated by commas well we had to overload method Disp 2 more times to make it able to process the 3 different types, But do we actually notice a difference between these 3 methods for me i see 1 difference only (The parameter type) which the method ask for .. But the method name is the same and even the method body is the same.

Generic Methods

Generic Methods enable you to specify with a single method declaration, a set of related methods .. Which means in the previous example i can use a generic method rather than make 3 methods, And the generic method will process any data type .. Little confused right ^^ Okay let’s check the next example which will make everything clear .. Have a look to the example and i’ll explain it.

static void Main(string[] args)
{
int[] intarray = { 1, 2, 3, 4, 5, 6, 7 };
double[] doublearray = { 1.12, 2.58, 3.65, 4.29, 5.78 };
string[] stringarray = { “Ibrahim”, “Zeyad”, “Emad”, “Nader”, “Amr” };
Disp(intarray);
Console.WriteLine();
Disp(doublearray);
Console.WriteLine();
Disp(stringarray);
}

public static void Disp <T> ( T [] x )
{
foreach (T element in x)
Console.Write(element + “, “);
}

Yes it’s real the method worked for int array, double array and string array, and if i passed a char or an object array or whatever array i’ll pass it will work very fine … I think now the word i said “General Model” is clear, But i didn’t explain yet and of course you have many answers in your thoughts.

All generic methods declaration have a Type-Parameter List delimited by angel brackets (<T> in this example) which follows the method name, Each Type-Parameter List contain one or more Type Parameters separated by commas, A Type Parameter is an identifier that’s used rather than actual type names, Type Parameter can be used as a return type for the method (Method return type can be T), Also the Type Parameter can be used in the method local variables and arguments (Check previous example method take argument x of type T means you can pass any array whatever it was it’s type as an argument for this method)

Note: Forget to include the Type-Parameter List when declaring a generic method will result a compilation error as the compiler wont recognize the Type Parameter names when they’re encountered in the method.

Note: If the compiler can’t find a single non-generic or generic method declaration that’s match the method call, Or if the compiler found multiple method matches the call, a compilation error will occur

Type Constraints

Well have anybody thought that you might need to delimit the types that the generic method process, I mean sometimes i may need a function that can’t be processed on all type, For example now i need to make a generic method that take 3 argument and return it’s maximum well since that i’ll have to use the > operator which i don’t know if every type provide the use of it … So what should i do!! Well it’s possible for me to compare objects of the same type using another thing rather than the > operator which is ICompareable<T> Interface lets discuss it and back again to our problem.

ICompareable<T> Interface: it’s an interface of namespace System, Types that implement ICompareable<T> must declare a method named CompareTo for comparing object we can use something like that x.CompareTo(y); well the method will return 0 if the two objects are equal, negative number if x is less than y, And positive number if x is greater than y, Well that’s great but we are talking about Objects, How about the simple data types (i.e., int, float, double, char, ..etc.), Well there is something called Structure for each data type in the Framework enable you to use the simple data type as an object and all the Structures implement ICompareable<T> interface, Structures Like (i.e., Int32 for int, Double for double, String for string, ..etc.)

Back to our problem okay now i’ll use CompareTo method to compare rather than > operator, But there is another problem !! Not all objects implements ICompareable<T> Interface so i need to do something telling the generic method (“Take only objects that can be compared as an argument”) Do you think i can do something like that?? Well yes and that what’s called Type Constraints

Type Constraints means that i restrict the type of the argument supplied to a particular Type Parameter let’s Check the next example and back again to explain it!!

static void Main(string[] args)
{
Console.WriteLine( Max(3, 5, 7));
Console.WriteLine( Max(4.5, 7.8, 8.9));
Console.WriteLine( Max(“Ahmed”,”Mohamed”,”Hussien”));
}

public static T Max <T> (T x, T y, T z)
where T: IComparable<T>
{
T max = x;
if (y.CompareTo(max) > 0)
max = y;
if (z.CompareTo(max) > 0)
max = z;
return max;
}

Well the method work properly ^^ But have anybody noticed anything new!! Yes the Where T: ICompareable<T> Hmmm.. Well i told that method “Don’t accept any object as an argument unless it implements ICompareable<T> Interface!! So by now the generic method will accept any object as it’s arguments only if i can compare them ^^ Well there is several Type Constraints C# provides let’s talk about them.

  • Class Constraint: Indicate that the Type Argument must be an object of specific class or an object of it’s subclasses.
  • Interface Constraint: Indicate that the Type Argument must be an object of a class that implement that interface (Like previous example).
  • Reference-Type Constraint: Indicate that the Type Argument must be a reference type argument using keyword class.
  • Value-Type Constraint: Indicate that the Type Argument must be a value type argument using keyword struct
  • Constructor Constraint: Indicate that the generic method can use the operator new() to create new objects of the Type Argument (which is passed to the method) using the keyword new().
  • Note: All Keywords that should be used as a Type Constraint you can declare them after where T:
  • Note: You can apply multiple constraints by separating them by commas, Taking in consideration that Class, Reference-Type, Value-Type Constraints MUST be listed first (And only one of these three can be used in a single generic method), Interface Constraint listed next, Constructor Constraint listed last!!

 

Well That was the first part discussing Generics there will be another part i’ll post later, Hope That You Liked It !! 🙂 🙂 🙂

Advertisements

One thought on “Generics Part I

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s