- C# Generics Introduction
- C# Generics 2
- C# Generic Constraints
- C# Generic Methods
- C# Enumerators
- C# Generic Enumeration Interfaces
- C# Iterators
The post C# Introduction lists all of the series of posts we have at this site.
This discussion is based on the book C# 7.0 Pocket Reference by Joseph Albahari and Ben Albahari published by O’Reilly Media Inc.
Generics is an advanced topic in C#. However, they can be very easy to use and they have already been discussed in Lists. In fact, you rarely need to create your own Generic types because most of the time you will be using those already provided by the .NET Framework.
A generic type declares type parameters, placeholder types to be filled in by the consumer of the generic type, which supplies the type arguments. Below is a generic type, Stack
public class Stack<T> { int position; T[] data = new T[100]; public void Push (T obj) => data[position++] = obj; public T Pop() => data[--position]; }
var stack = new Stack<int>(); stack.Push (5); stack.Push (10); int x = stack.Pop(); // x is 10 int y = stack.Pop(); // y is 5
Notice that no downcasts are required in the last two lines, avoiding the possibility of a runtime error and eliminating the overhead of boxing/unboxing. This makes our generic stack superior to a nongeneric stack that uses object in place of T.
Declaring a Generic Class
We’ve already done that in the first code listing, but know that you can have more than one type parameter. Between the angle brackets, you place a comma-separated list of the placeholder strings that represent the types, to be supplied on demand. These are called type parameters. You use the type parameters throughout the body of the declaration of the generic class to represent the types that should be substituted in by the compiler. There is no special keyword that flags a generic class declaration. Instead, the presence of the type parameter list, demarcated with angle brackets, distinguishes a generic class declaration from a regular class declaration.