C# Generics

The C# programming language has an essential feature known as generics. It enables us to create classes, methods, structures, delegates, and interfaces with a type placeholder. These placeholders are changed by the compiler with the specified type during compilation, which guarantees type safety and also improves performance.

Generics are mainly used to create general-purpose, reusable classes and methods that work with different data types without code duplication. We need to use angle brackets (<>) to define a generic class. The angle brackets are used to declare a class or method as a generic type and accept multiple type parameters.

Syntax:

It has the following syntax.

Example

public returnType MethodName<T>(T parameter)

{

    // Method body

}

In this syntax,

  • T: It represents a generic type parameter.
  • returnType: It specifies the method's return type.
  • MethodName: It represents the name of the method.
  • C# Generic Example

Let us take an example to illustrate the generic in C#.

Example

Example

using System;

class C# Tutorial

{

    // Generic method

    public static void Display<T>(T value)

    {

        Console.WriteLine("The value is " + value);

    }

    static void Main()

    {

        // Calling Generic method

        Display<int>(100);          

        Display<string>("John");   

        Display<double>(3.14);      

        Display<bool>(true);        

    }

}

Output:

Output

The value is 100

The value is John

The value is 3.14

The value is True

Explanation:

In this example, we have taken the generic method named Display, which can accept any type of value, such as int, string, double, or bool. After that, we call the Display method, the compiler automatically replaces T with the actual type value, and prints the result.

Types of Generics in C#

Generic allows the creation of flexible, reusable, and type-safe code. There are several ways to use generics in C#. Some of them are as follows:

Here, we will discuss these generics one by one.

1) Generic Class

A generic class is an important feature in C# that allows us to define type-safe data structures or classes that can run on different data types. The actual data type is specified when the class is instantiated, which provides greater flexibility and code reusability.

C# Generic Class Example

Let us take an example to illustrate the generic class in C#.

Example

Example

using System;

// Generic class

class Box<T>

{

    public T item;

}

class Program

{

    static void Main(string[] args)

    {

        Box<int> b = new Box<int>();

        b.item = 5;

        Console.WriteLine("Integer: " + b.item);

        Box<string> bb = new Box<string>();

        bb.item = "Hello";

        Console.WriteLine("String: " + bb.item);

    }

}

Output:

Output

Integer: 5

String: Hello

Explanation:

In this example, we have taken a class named Box<T>, where T can be any data type. In the main method, we create two instances of this generic class of integer and string type. The first instance is b, which holds the integer value, and the second instance is bb, which holds the string value.

2) Generic Method

In C#, a generic method is a method that is defined with multiple type parameters, which enables it to operate with different data types in a type-safe manner without code duplication. It is useful when we want to write a method that can handle different types without affecting performance or type safety.

Example of a Generic Method in C#

Let's take an example to illustrate the generic method in C#.

Example

Example

using System;

public class C# Tutorial

{

    // Generic Method

    public static void Swap<T>(ref T a, ref T b)

    {

        T tmp = a;

        a = b;

        b = tmp;

    }

    public static void Main()

    {

        int m = 5, n = 10;

        Console.WriteLine("The values before swapping are: m = " + m + ", n = " + n);

        Swap(ref m, ref n);

        Console.WriteLine("After swapping: m = " + m + ", n = " + n);

        string f = "Hello World", s = "Tech";

        Console.WriteLine("\nBefore swapping: first = " + f + ", second = " + s);                        Swap(ref f, ref s);

        Console.WriteLine("After swapping: first = " + f + ", second = " + s);

    }

}

Output:

Output

The values before swapping are: m = 5, n = 10

After swapping: m = 10, n = 5

Before swapping: first = C# Tutorial, second = Tech

After swapping: first = Tech, second = C# Tutorial

Explanation:

In this example, we have taken a class named C# Tutorial that contains the swapping<T> method, which takes two parameters by reference using the ref keyword. The method works to swap the values using a temporary variable. In the main method, the program first swaps two integers m and n, and prints their values before and after swapping. After that, it swaps the two strings f and s, and shows the output.

3) Generic Interface

In C#, a generic interface enables us to define a contract with multiple type parameters, which makes it flexible to work with various data types. It uses a type parameter, which avoids code duplication for multiple data types. It ensures type safety and code reusability.

C# Generic Interface Example

Let's take an example to illustrate a generic interface in C#.

Example

Example

using System;

// Generic interface

public interface ICalc<m>

{

    void square_root(m value);

}

public class dCalc : ICalc<double>

{

    public void square_root(double v)

    {

        double result = v * v;

   Console.WriteLine("The square of a number is " + result);

    }

}

public class C# Tutorial

{

    public static void Main()

    {

        ICalc<double> c = new dCalc();

        c.square_root(10); 

    }

}

Output:

Output

The square of a number is 100

Explanation:

In this example, we have taken an interface ICalc<m> that defines a method named squareroot that takes a parameter of a generic type m. After that, it creates a class dCalc and implements the interface using the type double. In the squareroot method, it calculates the square root of the number. In the main method, we create an object using the interface ICalc<double>, and then call the square_root method and print the output.

4) Generic Delegates

In C#, a generic delegate is a type of delegate that is defined with multiple type parameters, which enables it to work with any data type. If we don't want to create delegates for different data types, we can also define a generic delegate and reuse it with any type parameter.

C# Generic Delegate Example

Let us take an example to illustrate the generic delegates in C#.

Example

Example

using System;

namespace C# Tutorial

{		

    // Generic delegate	

    public delegate T Op<T>(T x, T y);

    class tech

    {

        // Method 

        static int add( int p, int q )

        {

            return p + q;

        }

        static string addchar( string p, string q )

        {

            return p + q;

        }

        static void Main(string[] args)

        {

            Op<int> o = add;

            Console.WriteLine("The Addition of integers: " + o(10, 20) );

            Op<string> Os = addchar;

            Console.WriteLine("The Concatenation of strings: " + Os("Hello, ", "World!") );

        }

    }

}

Output:

Output

The Addition of integers: 30

The Concatenation of strings: Hello, World!

Explanation:

In this example, we have taken a generic delegate Op<T> that can work with different parameters. After that, we create methods to add integers and join strings. In the main method, the delegate is used with an integer to add numbers and with a string to concatenate text.

5) Generic Collection

In C#, a generic collection is a special type of collection that is used to store any data type safely. These collections are defined in the System.Collections.Generic namespace. It is generally used in several collections, such as List<T>, Dictionary<TKey, TValue>, Queue<T>, Stack<T>, and many others.

C# Generic Collection Example

Let's take an example to illustrate the generic collection in C#.

Example

Example

using System;	

using System.Collections.Generic;

class C# Tutorial

{

    static void Main()

    {

        List<int> x = new List<int>();

        x.Add(8);

        x.Add(16);

        x.Add(32);

        Dictionary<string, int> a = new Dictionary<string, int>();

        a.Add("Michael", 45);

        a.Add("Bravo", 50);

        a.Add("Johnson", 35);

        Console.WriteLine("The numbers are: ");

        foreach (int nn in x)

        {

            Console.WriteLine(nn);

        }

        Console.WriteLine("The ages are: ");

        foreach (var item in a)

        {

            Console.WriteLine(item.Key + ": " + item.Value);

        }

    }

}

Output:

Output

The numbers are: 

8

16

32

The ages are: 

Michael: 45

Bravo: 50

Johnson: 35

Explanation:

In this example, we have taken a List<int> to store integer values, and a Dictionary <string, int> to store names with their ages. After that, we take a foreach loop to print their value in a type-safe manner.

Advantages of using Generics in C#

There are several advantages of generics in C#. Some of the main advantages are as follows.

Here, we will discuss these advantages one by one.

1) Code Reusability

In C#, generics provide code reusability by enabling us to define a single method, class, or interface that can work with different data types.

2) Type Safety

Generics provide better type safety by ensuring that only the specified data type is used. It helps to find errors at compile time instead of runtime, which makes the code more reliable and robust.

3) Performance

Generic type provides better performance compared to non-generic types. It reduces several unnecessary operations, such as boxing, unboxing, and explicit type casting.

4) Support for Multiple Type Parameters

In C#, Generic classes and methods can accept more than one type of parameter. It offers greater flexibility, a more versatile, and reusable code structure.

5) Collections

In C#, generics can be used in different collections, such as List<T>, Dictionary<T, U>, etc. It provides type-safe and efficient data structures.

Conclusion

In conclusion, C# generics are an important feature that enables us to define classes and methods with a type placeholder for data types. The compiler replaces these placeholders with the specified type during compile time. It allows us to define a single method or class that can be reused with different data types. With the use of generic classes, methods, interfaces, delegates, and collections, we can create applications that are more efficient, flexible, and maintainable.

C# Generics FAQs

1) What is Generic in C#?

In C#, generic is a concept that allows us to define classes and methods with a type placeholder. The compiler replaces these type placeholders with the specified type at compile time. It allows us to create applications with more flexible, type-safe, and reusable code.

2) Can we use multiple type parameters in C# Generics?

Yes, we can use multiple type parameters in Generics in C#.

Example

public class Pair<T1, T2>

{

    public T1 First;

    public T2 Second;

}

3) What are the default (T) generics in C#?

In C#, the default (T) is an expression that is used to return the default value of a type T. It is generally used in classes and methods when the specific type is not known at compile time.

4) Define a Generic collection in C#?

In C#, a generic collection is a special type of collection that can store any data type safely. It is defined in the System.Collections.Generic namespace. It is generally used in collections such as List<T>, Dictionary<TKey, TValue>, Queue<T>, Stack<T>, and many others.

5) What is the downside of Generics in C#?

If the generic is not used correctly in C#, it may lead to increased code complexity and can be misused. They can make code harder to read for beginners, and reflection with generics can be more complex. However, proper utilization of generics can reduce these types of issues.

Input Required

This code uses input(). Please provide values below: