What exactly is an "open generic type" in .NET?

.net, c#, generics, open-generics

Solution

The C# language defines an open type to be a type that's either a type argument or a generic type defined with unknown type arguments:

All types can be classified as either open types or closed types. An open type is a type that involves type parameters. More specifically:

- A type parameter defines an open type.

- An array type is an open type if and only if its element type is an open type.

- A constructed type is an open type if and only if one or more of its type arguments is an open type. A constructed nested type is an open type if and only if one or more of its type arguments or the type arguments of its containing type(s) is an open type.

A closed type is a type that is not an open type.

Therefore `T`, `List<T>`, and `Dictionary<string,T>`, and `Dictionary<T,U>` are all open types (`T` and `U` are type arguments) whereas `List<int>` and `Dictionary<string,int>` are closed types.

There's a related concept: An unbound generic type is a generic type with unspecified type arguments. An unbound type can't be used in expressions other than `typeof()` and you can't instantiate it or call its methods. For instance, `List<>` and `Dictionary<,>` are unbound types.

To clarify the subtle distinction between an open type and an unbound type:

class Program {
   static void Main() { Test<int>(); }
   static void Test<T>() {
      Console.WriteLine(typeof(List<T>)); // Print out the type name
   }
}

If you run this snippet, it'll print out

System.Collections.Generic.List`1[System.Int32]

which is the CLR name for `List<int>`. It's clear at runtime that the type argument is `System.Int32`. This makes `List<T>` a bound open type.

At runtime, you can use reflection to bind type arguments to unspecified type parameters of unbound generic types with the `Type.MakeGenericType` method:

Type unboundGenericList = typeof(List<>);
Type listOfInt = unboundGenericList.MakeGenericType(typeof(int));
if (listOfInt == typeof(List<int>))
     Console.WriteLine("Constructed a List<int> type.");

You can check whether a type is an unbound generic type (generic type definition) from which you can construct bound types with the `Type.IsGenericTypeDefinition` property:

Console.WriteLine(typeof(Dictionary<,>).IsGenericTypeDefinition); // True
Console.WriteLine(typeof(Dictionary<int,int>).IsGenericTypeDefinition); // False

To get the unbound type from a constructed type at runtime, you can use the `Type.GetGenericTypeDefinition` method.

Type listOfInt = typeof(List<int>);
Type list = listOfInt.GetGenericTypeDefinition(); // == typeof(List<>)

Note that for a generic type, you can either have a completely unbound type definition, or a completely bound definition. You can't bind some type parameters and leave others unbound. For instance, you can't have `Dictionary<int,>` or `Dictionary<,string>`.

Problem

I was going through Asp.Net MVC lesson and learned that, for a method to qualify as an action for a controller, - It must not have an "open generic type" I understand generics somewhat and use them to some extent, but: - What is an open generic type in .Net. - Is there such a thing as a closed generic type? - Open generic type is a term not used very often. What is used / confused with it ?

Original source

Related problems