public void SomeMethod <T> () { }
public void SomeMethod<T, V>() { }
public T SomeMethod<T>(IEnumerable<T> sequence) { ... }
public void SomeMethod<T>() where T : new() { }
public void SomeMethod<T, V>() where T : new() where V : struct { }
public void SomeMethod<T>() where T: IDisposable { }
public void SomeMethod<T>() where T: Foo { }
public class MyClass<T> { public T Data {get; set; } }
Parameter(s) | Description |
---|---|
T, V | Type placeholders for generic declarations |
Generics in C# are supported all the way down to the runtime: generic types built with C# will have their generic semantics preserved even after compiled to CIL.
This effectively means that, in C#, it is possible to reflect on generic types and see them as they were declared or check if an object is an instance of a generic type, for example. This is in contrast with type erasure, where generic type information is removed during compilation. It is also in contrast with the template approach to generics, where multiple concrete generic types become multiple non-generic types at runtime, and any metadata required to further instantiate the original generic type definitions is lost.
Be careful, however, when reflecting on generic types: generic types' names will be altered on compilation, substituting the angled brackets and the type parameters' names by a backtick followed by the number of generic type parameters. Thus, a Dictionary<TKey, Tvalue>
will be translated to Dictionary`2
.