Поделиться через


Type.MakeGenericType Method

Microsoft Silverlight will reach end of support after October 2021. Learn more.

Updated: June 2010

Substitutes the elements of an array of types for the type parameters of the current generic type definition and returns a Type object representing the resulting constructed type.

Namespace:  System
Assembly:  mscorlib (in mscorlib.dll)

Syntax

'Declaration
Public Overridable Function MakeGenericType ( _
    ParamArray typeArguments As Type() _
) As Type
public virtual Type MakeGenericType(
    params Type[] typeArguments
)

Parameters

  • typeArguments
    Type: array<System.Type[]
    An array of types to be substituted for the type parameters of the current generic type.

Return Value

Type: System.Type
A Type representing the constructed type formed by substituting the elements of typeArguments for the type parameters of the current generic type.

Exceptions

Exception Condition
InvalidOperationException

The current type does not represent a generic type definition. That is, IsGenericTypeDefinition returns false.

ArgumentNullException

typeArguments is nulla null reference (Nothing in Visual Basic).

-or-

Any element of typeArguments is nulla null reference (Nothing in Visual Basic).

ArgumentException

The number of elements in typeArguments is not the same as the number of type parameters in the current generic type definition.

-or-

Any element of typeArguments does not satisfy the constraints specified for the corresponding type parameter of the current generic type.

-or-

typeArguments contains an element that is a pointer type (Type.IsPointer returns true), a ByRef type (Type.IsByRef returns true), or Void.

NotSupportedException

The invoked method is not supported in the base class. Derived classes must provide an implementation.

Remarks

The MakeGenericType method allows you to write code that assigns specific types to the type parameters of a generic type definition, thus creating a Type object that represents a particular constructed type. You can use this Type object to create run-time instances of the constructed type.

Types constructed with MakeGenericType can be open, that is, some of their type arguments can be type parameters of enclosing generic methods or types. You might use such open constructed types when you emit dynamic assemblies. For example, consider the classes Base and Derived in the following code.

Public Class Base(Of T, U)
End Class
Public Class Derived(Of V)
    Inherits Base(Of Integer, V)
End Class
public class Base<T, U> { }
public class Derived<V> : Base<int, V> { }
generic<typename T, typename U> 
    public ref class Base { };
generic<typename V> 
    public ref class Derived : Base<int, V> { };

To generate Derived in a dynamic assembly, it is necessary to construct its base type. To do this, call the MakeGenericType method on a Type object representing the class Base, using the generic type arguments Int32 and the type parameter V from Derived. Because types and generic type parameters are both represented by Type objects, an array containing both can be passed to the MakeGenericType method.

NoteNote:

A constructed type such as Base<int, V> is useful when emitting code, but you cannot call the MakeGenericType method on this type because it is not a generic type definition. To create a closed constructed type that can be instantiated, first call the GetGenericTypeDefinition method to get a Type object representing the generic type definition and then call MakeGenericType with the desired type arguments.

The Type object returned by MakeGenericType is the same as the Type obtained by calling the GetType method of the resulting constructed type, or the GetType method of any constructed type that was created from the same generic type definition using the same type arguments.

NoteNote:

An array of generic types is not itself a generic type. You cannot call MakeGenericType on an array type such as C<T>[] (Dim ac() As C(Of T) in Visual Basic). To construct a closed generic type from C<T>[], call GetElementType to obtain the generic type definition C<T>; call MakeGenericType on the generic type definition to create the constructed type; and finally call the MakeArrayType method on the constructed type to create the array type. The same is true of pointer types and ref types (ByRef in Visual Basic).

For a list of the invariant conditions for terms used in generic reflection, see the IsGenericType property remarks.

Nested Types

If a generic type is defined using C#, C++, or Visual Basic, then its nested types are all generic. This is true even if the nested types have no type parameters of their own, because all three languages include the type parameters of enclosing types in the type parameter lists of nested types. Consider the following classes:

Public Class Outermost(Of T)
    Public Class Inner(Of U)
        Public Class Innermost1(Of V)
        End Class
        Public Class Innermost2
        End Class
    End Class
End Class
public class Outermost<T>
{
    public class Inner<U>
    {
        public class Innermost1<V> {}
        public class Innermost2 {}
    }
}
generic<typename T> public ref class Outermost
{
public:
    generic<typename U> ref class Inner
    {
    public:
        generic<typename V> ref class Innermost1 {};
        ref class Innermost2 {};
    };
};

The type parameter list of the nested class Inner has two type parameters, T and U, the first of which is the type parameter of its enclosing class. Similarly, the type parameter list of the nested class Innermost1 has three type parameters, T, U, and V, with T and U coming from its enclosing classes. The nested class Innermost2 has two type parameters, T and U, which come from its enclosing classes.

If the parameter list of the enclosing type has more than one type parameter, all the type parameters in order are included in the type parameter list of the nested type.

To construct a generic type from the generic type definition for a nested type, call the MakeGenericType method with the array formed by concatenating the type argument arrays of all the enclosing types, beginning with the outermost generic type, and ending with the type argument array of the nested type itself, if it has type parameters of its own. To create an instance of Innermost1, call the MakeGenericType method with an array containing three types, to be assigned to T, U, and V. To create an instance of Innermost2, call the MakeGenericType method with an array containing two types, to be assigned to T and U.

The languages propagate the type parameters of enclosing types in this fashion so you can use the type parameters of an enclosing type to define fields of nested types. Otherwise, the type parameters would not be in scope within the bodies of the nested types. It is possible to define nested types without propagating the type parameters of enclosing types, by emitting code in dynamic assemblies or by using the Microsoft intermediate language (MSIL) assembler. Consider the following code for the MSIL assembler:

.class public Outer<T> {
    .class nested public Inner<U> {
        .class nested public Innermost {
        }
    }
}

In this example, it is not possible to define a field of type T or U in class Innermost, because those type parameters are not in scope. The following assembler code defines nested classes that behave the way they would if defined in C++, Visual Basic, and C#:

.class public Outer<T> {
    .class nested public Inner<T, U> {
        .class nested public Innermost<T, U, V> {
        }
    }
}

You can use the MSIL disassembler to examine nested classes defined in the high-level languages and observe this naming scheme. For information on the disassembler, see the MSIL Disassembler (Ildasm.exe) in the full .NET Framework documentation.

Examples

The following example uses the MakeGenericType method to create a constructed type from the generic type definition for the Dictionary<TKey, TValue> type. The constructed type represents a Dictionary<TKey, TValue> of Test objects with string keys.

Imports System.Reflection
Imports System.Collections.Generic

Public Class Example
   Public Shared Sub Demo(ByVal outputBlock As System.Windows.Controls.TextBlock)
      outputBlock.Text &= vbCrLf & "--- Create a constructed type from the generic Dictionary type." & vbCrLf

      ' Create a type object representing the generic Dictionary 
      ' type, by omitting the type arguments (but keeping the 
      ' comma that separates them, so the compiler can infer the
      ' number of type parameters).
      Dim generic As Type = GetType(Dictionary(Of ,))
      DisplayTypeInfo(outputBlock, generic)

      ' Create an array of types to substitute for the type
      ' parameters of Dictionary. The key is of type string, and
      ' the type to be contained in the Dictionary is Example.
      Dim typeArgs() As Type = {GetType(String), GetType(Example)}

      ' Create a Type object representing the constructed generic
      ' type.
      Dim constructed As Type = generic.MakeGenericType(typeArgs)
      DisplayTypeInfo(outputBlock, constructed)

      ' Compare the type objects obtained above to type objects
      ' obtained using GetType() and GetGenericTypeDefinition().
      outputBlock.Text &= vbCrLf & "--- Compare types obtained by different methods:" & vbCrLf

      Dim t As Type = GetType(Dictionary(Of String, Example))
      outputBlock.Text &= vbTab & "Are the constructed types equal? " _
          & (t Is constructed) & vbCrLf
      outputBlock.Text &= vbTab & "Are the generic types equal? " _
          & (t.GetGenericTypeDefinition() Is generic) & vbCrLf
   End Sub

   Private Shared Sub DisplayTypeInfo(ByVal outputBlock As System.Windows.Controls.TextBlock, ByVal t As Type)
      outputBlock.Text &= vbCrLf & t.ToString() & vbCrLf

      outputBlock.Text &= vbTab & "Is this a generic type definition? " _
          & t.IsGenericTypeDefinition & vbCrLf

      outputBlock.Text &= vbTab & "Is it a generic type? " _
          & t.IsGenericType & vbCrLf

      Dim typeArguments() As Type = t.GetGenericArguments()
      outputBlock.Text &= String.Format(vbTab & "List type arguments ({0}) & vbCrLf:", _
          typeArguments.Length)
      For Each tParam As Type In typeArguments
         outputBlock.Text &= vbTab & vbTab & tParam.ToString() & vbCrLf
      Next
   End Sub
End Class

' This example produces the following output:
'
'--- Create a constructed type from the generic Dictionary type.
'
'System.Collections.Generic.Dictionary'2[TKey,TValue]
'        Is this a generic type definition? True
'        Is it a generic type? True
'        List type arguments (2):
'                TKey
'                TValue
'
'System.Collections.Generic.Dictionary`2[System.String,Test]
'        Is this a generic type definition? False
'        Is it a generic type? True
'        List type arguments (2):
'                System.String
'                Test
'
'--- Compare types obtained by different methods:
'        Are the constructed types equal? True
'        Are the generic types equal? True
using System;
using System.Reflection;
using System.Collections.Generic;

public class Example
{
   public static void Demo(System.Windows.Controls.TextBlock outputBlock)
   {
      outputBlock.Text += "\r\n--- Create a constructed type from the generic Dictionary type." + "\n";

      // Create a type object representing the generic Dictionary 
      // type, by omitting the type arguments (but keeping the 
      // comma that separates them, so the compiler can infer the
      // number of type parameters).      
      Type generic = typeof(Dictionary<,>);
      DisplayTypeInfo(outputBlock, generic);

      // Create an array of types to substitute for the type
      // parameters of Dictionary. The key is of type string, and
      // the type to be contained in the Dictionary is Example.
      Type[] typeArgs = { typeof(string), typeof(Example) };

      // Create a Type object representing the constructed generic
      // type.
      Type constructed = generic.MakeGenericType(typeArgs);
      DisplayTypeInfo(outputBlock, constructed);

      // Compare the type objects obtained above to type objects
      // obtained using typeof() and GetGenericTypeDefinition().
      outputBlock.Text += "\r\n--- Compare types obtained by different methods:" + "\n";

      Type t = typeof(Dictionary<String, Example>);
      outputBlock.Text += String.Format("\tAre the constructed types equal? {0}", t == constructed) + "\n";
      outputBlock.Text += String.Format("\tAre the generic types equal? {0}",
          t.GetGenericTypeDefinition() == generic) + "\n";
   }

   private static void DisplayTypeInfo(System.Windows.Controls.TextBlock outputBlock, Type t)
   {
      outputBlock.Text += String.Format("\r\n{0}", t) + "\n";

      outputBlock.Text += String.Format("\tIs this a generic type definition? {0}",
          t.IsGenericTypeDefinition) + "\n";

      outputBlock.Text += String.Format("\tIs it a generic type? {0}",
          t.IsGenericType) + "\n";

      Type[] typeArguments = t.GetGenericArguments();
      outputBlock.Text += String.Format("\tList type arguments ({0}):", typeArguments.Length) + "\n";
      foreach (Type tParam in typeArguments)
      {
         outputBlock.Text += String.Format("\t\t{0}", tParam) + "\n";
      }
   }
}

/* This example produces the following output:

--- Create a constructed type from the generic Dictionary type.

System.Collections.Generic.Dictionary`2[TKey,TValue]
        Is this a generic type definition? True
        Is it a generic type? True
        List type arguments (2):
                TKey
                TValue

System.Collections.Generic.Dictionary`2[System.String, Test]
        Is this a generic type definition? False
        Is it a generic type? True
        List type arguments (2):
                System.String
                Test

--- Compare types obtained by different methods:
        Are the constructed types equal? True
        Are the generic types equal? True
 */

Version Information

Silverlight

Supported in: 5, 4, 3

Silverlight for Windows Phone

Supported in: Windows Phone OS 7.1, Windows Phone OS 7.0

XNA Framework

Supported in: Xbox 360, Windows Phone OS 7.0

Platforms

For a list of the operating systems and browsers that are supported by Silverlight, see Supported Operating Systems and Browsers.

Change History

Date

History

Reason

June 2010

Added missing causes for ArgumentException exception.

Customer feedback.