In C #, the “T” parameter is often used to define functions that take any type. They are used to write generic classes and methods that can work with any type of data while maintaining strict type safety. We’ll discuss how they work and how to use them.
How does it work?
The variable “T” that you have probably seen in some method definitions is called a Generic type parameter, or just a “generic”
For example, collections use generics so that they can handle whatever the user throws at them. There is no other definition for
List;; Instead, there is a definition for
In practice it looks like this. Even if this is a class and not a method, you can pass the type parameters using
Bracket syntax. Wherever you need to reference something of this type, just replace the parameter instead.
In fact, you can name this T variable anything you want, although it is common practice to at least start it with “T”. If you have a function that takes arguments of multiple types, you can name them differently; B. “TOutput” or “TInput”. This is often used in delegate definitions and in dictionaries where you have TKey and TValue.
Of course, you can also use generics in methods as well as interfaces and delegates. They work the same way, and you can even pass the type parameter to another function as a type parameter.
In particular, you can use the type parameter in the actual parameters of the function. You still have to enter it
<> Parentheses, otherwise it’s just an invalid type, but you can use the parameter anywhere in the definition of this method.
They are particularly useful with delegates as they allow you to accept functions with variable parameters.
Generics are great, but it can cause some problems if the feature is allowed to be whatever type you throw at it. Sometimes it is best to put some restrictions on its use.
This is done with the
where T : Syntax. The simplest form of this is
where T : ClassNamewhich ensures that the T parameter must be of the specified type or must be derived
ClassName. This enables a type-safe polymorphism, like this function, that takes any type of fruit and returns a
List, rather than a
Listwhich would be technically correct but would lose valuable type information.
You can see the compiler yelling at you when we try to use this function on something that isn’t a fruit.
In addition to simple inheritance, there are a few other useful limitations:
where T : InterfaceName– to like
T : ClassNamehowever, it ensures that the type argument implements the specified interface.
where T : class– ensures that the type argument is a reference type.
where T : struct– ensures that the type argument is a non-nullable value type.
where T : notnull– The type argument must be a non-nullable type.
where T : new()– The type argument must be able to be created without parameters.
where T : TOther– the type argument
Tmust be the type argument or be derived from it
You can specify multiple restrictions in a comma-separated list.