Chapter 4. Generics
In Chapter 3, I showed how to write types and described the various kinds of members they can contain. However, there’s an extra dimension to classes, structs, interfaces, and methods that I did not show. They can define type parameters, placeholders that let you plug in different types at compile time. This allows you to write just one type and then produce multiple versions of it. A type that does this is called a generic type. For example, the runtime libraries define a generic class called List<T> that acts as a variable-length array. T is a type parameter here, and you can use almost any type as an argument, so List<int> is a list of integers, List<string> is a list of strings, and so on.1 You can also write a generic method, which is a method that has its own type arguments, independently of whether its containing type is generic.
Generic types and methods are visually distinctive because they always have angle brackets (< and >) after the name. These contain a comma-separated list of parameters or arguments. The same parameter/argument distinction applies here as with methods: the declaration specifies a list of parameters, and then when you come to use the method or type, you supply arguments for those parameters. So List<T> defines a single type parameter, T, and List<int> supplies a type argument, int, for that parameter.
You can use any name you like for type parameters, within the usual constraints for identifiers in C#, but there are some popular ...