# Generic Class and Generic Method in C#

In C#, we can also have generic classes and generic methods i.e., classes and methods not made for a specific type but can be used with any general type.

We use <> brackets for this purpose. Suppose, we have defined a class or method with <T> and performed each operation on T inside the method or the class. And we passed an integer while calling it - <int>, then the T inside the class or the method will be changed to take int during the time of compilation.

Let's look at generic classes first.

## C# Generic Class

Let's take an example.

using System;

class Generic<T>
{
private T genericVariable;

public Generic(T genericValue)
{
this.genericVariable = genericValue;
}

public void Display()
{
Console.WriteLine(this.genericVariable);
}
}

class Test
{
static void Main(string[] args)
{
Generic<int> g = new Generic<int>(5);

Generic<string> g1 = new Generic<string>("CodesDope");

g.Display();
g1.Display();
}
}

5
CodesDope

In the above example, we have defined a generic class - class Generic<T>. Inside the class, we have treated T as normal data and declared a variable of type T - private T genericVariable;.

In the constructor also, we are taking a variable of type T - public Generic(T genericValue). Remember that the type of T will be decided during making the object of the class.

Generic<int> g = new Generic<int>(5); → Here, the type of T is an integer. So, T will become int inside the definition of the class.

Generic<string> g1 = new Generic<string>("CodesDope"); → In the object g1, T is string. So, T will become a string inside the definition of the class.

After execution of Generic<int> g = new Generic<int>(5);, Generic class would be something like:

class Generic
{
private int genericVariable;

public Generic(int genericValue)
{
this.genericVariable = genericValue;
}

public void Display()
{
Console.WriteLine(this.genericVariable);
}
}


Let's take one more example.

using System;

class Generic<T, U>
{
public T GenericVariableFirst
{
get;
set;
}

public U GenericVariableSecond
{
get;
set;
}
}

class Test
{
static void Main(string[] args)
{
Generic<int, string> g = new Generic<int, string>();

g.GenericVariableFirst = 10;
g.GenericVariableSecond = "abc";

Console.WriteLine(g.GenericVariableFirst);
Console.WriteLine(g.GenericVariableSecond);
}
}

10
abc

In this example, we have defined our class to work on two generic types - T and U i.e., class Generic<T, U>.

While making the object, we have set T as int and U as string - Generic<int, string> g.

## C# Constraint

We used a placeholder T in the above examples and this placeholder can be of any type. In C#, we can also constraint the type of placeholder using the where keyword. Suppose, we have defined a class as:

class ClassName<T> where T: class

In this case, T can only be reference type like class, string, etc. If we try with something else, we will get an error.

Here, class in where T: class means T can be a reference type. Let's look at the table given below for another type of constraints.

Constraint Description
class Must be reference type
struct Must be value type
new() Must have public parameterless constructor.
BaseClassName Must be derivied from BaseClassName class.
InterfaceName Must implement InterfaceName interface.
U Must be or derive from the argument supplied for U.

Let's take an example.

using System;

class Generic<T> where T: class
{
public T GenericVariable
{
get;
set;
}
}

class Test
{
static void Main(string[] args)
{
Generic<int> g = new Generic<int>();

g.GenericVariable = 10;

Console.WriteLine(g.GenericVariable);
}
}

hello.cs(16,5): error CS0452: The type 'int' must be a reference type in order to use it as type parameter 'T' in the generic type or method 'Generic<T>'
hello.cs(16,26): error CS0452: The type 'int' must be a reference type in order to use it as type parameter 'T' in the generic type or method 'Generic<T>'

In this example, we constrained the placeholder to take only reference type using class and we tried to make an object with an integer for the placeholder. Since int is a value type, we got errors during compiling the code.

Let's try with a reference type.

using System;

class Generic<T> where T: class
{
public T GenericVariable
{
get;
set;
}
}

class Test
{
static void Main(string[] args)
{
Generic<string> g = new Generic<string>();

g.GenericVariable = "CodesDope";

Console.WriteLine(g.GenericVariable);
}
}

CodesDope

In this example, we tried with a string which is a reference type and thus, the code compiled successfully.

### C# Multiple Constraints

We can also have multiple constraints. Let's take an example.

using System;

class Generic<T, U> where T: class where U: struct
{
public T GenericVariableFirst
{
get;
set;
}

public U GenericVariableSecond
{
get;
set;
}
}

class Test
{
static void Main(string[] args)
{
Generic<string, int> g = new Generic<string, int>();

g.GenericVariableFirst = "CodesDope";
g.GenericVariableSecond = 10;

Console.WriteLine(g.GenericVariableFirst);
Console.WriteLine(g.GenericVariableSecond);
}
}

CodesDope
10

## Inheritance With Generic Class in C#

We can derive a generic class to make subclasses of it. Let's take and example.

using System;

class Generic<T>
{
public T GenericVariable
{
get;
set;
}
}

class Derived: Generic<int>
{

}

class Test
{
static void Main(string[] args)
{
Derived d = new Derived();
}
}


In this example, we have made a subclass of a generic class and passed int during deriving it - class Derived: Generic<int>.

We can also make the derived class a generic class.

using System;

class Generic<T>
{
public T GenericVariable
{
get;
set;
}
}

class Derived<T>: Generic<T>
{

}

class Test
{
static void Main(string[] args)
{
Derived<int> d = new Derived<int>();
}
}


## C# Generic Methods

We can also have generic methods similar to a generic class. Let's take an example.

using System;

class Test
{
static void Display<T>(T message)
{
Console.WriteLine(message);
}

static void Main(string[] args)
{
Display("CodesDope");
Display(10);
}
}

CodesDope
10

In this example, we have a generic method Display which has a placeholder T.

Display("CodesDope");
Display(10);

Firstly, we passed a string and then an integer to the function Display and it worked fine.