Introduction to C# Generics

05 February 2021 at 10:00 by ParTech Media - Post a comment

The word ‘Generic’ means ‘not specific’. In other words, it is a generic form of representing an element. In the software world, generic solutions are the need of the hour. What we need is a solution that can solve multiple problems of similar nature without any alteration to the solution.

Similarly, while the code is being developed, there will be scenarios encountered by the developers where they have multiple data types in the same way. For example, we have a list of strings in a code. In it, we perform certain operations using the built-in functionality of the list. Similarly, there is a list of integers in the code, where we have the freedom to perform the operations using the built-in list functionality.

Imagine, there is a need to implement a user-defined functionality and it has to be common and work with all the primitive data types and user-defined data types. So there is a need to create a generic class similar to List (that comes with C# collections) and it should contain methods similar to the ones that are in lists (Add, AddRange, Where, etc.). And the methods should also work with the same set of data types as the new class.

So, how to create a user-defined class that can have data types assigned at run time and executes methods that are part of it? To answer this question, C# comes with a feature called Generics. Let's see in detail about what is C# Generics in this blog.

Table of contents

  1. What is C# Generics?
  2. Features of C# generics
  3. Generics Application
  4. Conclusion

What is C# Generics?

C# allows users to define classes, methods, static methods, interfaces, abstract classes, properties, events, delegates, and operators. This is done using a placeholder that can hold different data types. Also, it is achieved without defining the data types during the definition of the class, which makes it handy for the developers to use it for any data types. This feature of C# is called Generics.

Generics were introduced as a part of .Net Framework 2.0 and it is available under the namespace - System.Collections.Generic. It provides type-safe data structures. Generics help in improving the code reusability, type safety and have better performance as it does not require boxing, unboxing, and typecasting of variables and objects. Creating objects of the generic class is similar to the normal object instantiation.

Features of C# generics

A generic class can be a base class as well as a derived class.

Reusability - Without any code changes, generic type definition can be used for multiple purposes. For example, the same generic method can be used to add two integers, float, long, etc.

Type safety - Though generic provides options to use multiple data types for achieving the same purpose, it is very much type-safe.

Performance - Generics provide better performance over normal system types as they reduce the need for typecasting, boxing, and unboxing.

Generics Application

Generic Class and Property

Generic classes are defined using class name followed by type parameters inside angular brackets.

class PartechGenerics<T>

{

 }

In the above example, PartechGenerics is the class name and T is the type parameter. The type parameter can be used for the fields, properties, return types, and delegates inside the class.

class PartechGenerics<T>

{

​    	public T Info { get; set; }

}

In the above example, Info is a property present in the class PartechGenerics and Info is of the parameter type.

In the above two examples, we saw a single type parameter (T) being used for creating a custom class. Let's see how to create a generic class using multiple parameters in the following example.

class PartechMultipleParameters<TKey, TValue>

{  

}

Here, TKey and TValue are type parameters.  

Instantiating a generic class is similar to a regular class. But, in addition to it, the data type has to be specified. So, let's take the first code block where we have created the PartechGenerics class and see how to instantiate it.

PartechGenerics<string> partechGenerics = new PartechGenerics<string>(); 

In the above code, we have instantiated the generic class with data type as a string. So, the type parameter that is being used in the class will be replaced with the data type string at the run-time.

Similarly, the code allows the properties to be accessed using the object that is instantiated.

partechGenerics.Info = “This is a test string”;

The ‘Info’ property is of T type. At compile-time, the data type of the property is changed to string for the particular object instance and it allows assigning a string value to it.

Generic classes can also be used as a Base/Derived class. If Generic classes are the base class, then -

class DerivedClass : PartechGenerics<string>

{ 

}

In the above example, the generic class is assigned with the type as a string. So, the properties and methods that use the T type parameter will be converted to the data type string. In case, if we need to create a generic derived class, then use -

class DerivedClass<T> : PartechGenerics<T>

{

}

Generic Method

class PartechGenerics<T>

{

​    public void WriteMessage<T>(T inputData)  

​    {  

Console.WriteLine(inputData);  

​    }  

}

In the above example, we have a generic method ‘WriteMessage’. The role of the method is to write the input text in the console window, and it accepts all data types. The method can be accessed using the object that is instantiated for the class PartechGenerics.

Also, generic methods can have primitive data types, user-defined data types, and T type parameters together as input parameters and the same are applicable for the return type.

Also, generic methods can be used within a non-generic class.

class PartechNonGeneric

{

​    	public void WriteMessage<T>(T inputData)

​    	{

​          	Console.WriteLine(inputData);

​    	}

}

var partechNonGeneric = new PartechNonGeneric();

partechNonGeneric.WriteMessage(“This is a test method”);

partechNonGeneric.WriteMessage(123); 

Note - It is not mandatory to specify the type of t type parameter explicitly while calling the method as the code would infer the data type from the value specified.

partechNonGeneric.WriteMessage<int>(123); //Explicitly specified data type 

Conclusion

Generics are easy to implement and provide cleaner code for understanding and execution. The angular brackets represent that the class/method is a generic type. And the compiler will replace all the placeholders with the data type provided. As it is done at compile-time, any human errors while implementing it will be thrown as build errors.

Latest