Genéricos em tempo de execução (Guia de Programação em C#)Generics in the Run Time (C# Programming Guide)

Um tipo genérico ou método compilado em Microsoft Intermediate Language (MSIL) conterá metadados que o identificarão como possuidor de parâmetros de tipo.When a generic type or method is compiled into Microsoft intermediate language (MSIL), it contains metadata that identifies it as having type parameters. O uso de MSIL em um tipo genérico será diferente de acordo com o parâmetro de tipo fornecido, ou seja, se ele é um tipo de valor ou um tipo de referência.How the MSIL for a generic type is used differs based on whether the supplied type parameter is a value type or reference type.

Quando um tipo genérico é construído pela primeira vez com um tipo de valor como parâmetro, o tempo de execução cria um tipo genérico especializado com o(s) parâmetro(s) fornecido(s) substituído(s) nos locais apropriados do MSIL.When a generic type is first constructed with a value type as a parameter, the runtime creates a specialized generic type with the supplied parameter or parameters substituted in the appropriate locations in the MSIL. Os tipos genéricos especializados são criados uma vez para cada tipo de valor único usado como parâmetro.Specialized generic types are created one time for each unique value type that is used as a parameter.

Por exemplo, caso o código do programa declarar uma pilha construída de inteiros:For example, suppose your program code declared a stack that is constructed of integers:

Stack<int> stack;

Neste ponto, o tempo de execução gerará uma versão especializada da classe Stack<T> com o inteiro substituído corretamente, de acordo com seu parâmetro.At this point, the runtime generates a specialized version of the Stack<T> class that has the integer substituted appropriately for its parameter. Agora, sempre que o código do programa utilizar uma pilha de inteiros, o tempo de execução reutilizará a classe especializada Stack<T> gerada.Now, whenever your program code uses a stack of integers, the runtime reuses the generated specialized Stack<T> class. No exemplo a seguir, são criadas duas instâncias de uma pilha de inteiros e eles compartilham uma única instância do código Stack<int>:In the following example, two instances of a stack of integers are created, and they share a single instance of the Stack<int> code:

Stack<int> stackOne = new Stack<int>();
Stack<int> stackTwo = new Stack<int>();

No entanto, suponha que outra classe Stack<T> com um tipo de valor diferente – como long ou uma estrutura definida pelo usuário como parâmetro – foi criada em outro ponto do código.However, suppose that another Stack<T> class with a different value type such as a long or a user-defined structure as its parameter is created at another point in your code. Como resultado, o tempo de execução gerará outra versão do tipo genérico e substituirá um long nos locais apropriados no MSIL.As a result, the runtime generates another version of the generic type and substitutes a long in the appropriate locations in MSIL. Conversões não são mais necessárias, pois cada classe genérica especializada contém o tipo de valor nativamente.Conversions are no longer necessary because each specialized generic class natively contains the value type.

Os genéricos funcionam de outro modo nos tipos de referência.Generics work somewhat differently for reference types. Na primeira vez em que um genérico é construído com qualquer tipo de referência, o tempo de execução cria um tipo genérico especializado com referências de objeto substituídas por parâmetros no MSIL.The first time a generic type is constructed with any reference type, the runtime creates a specialized generic type with object references substituted for the parameters in the MSIL. Em seguida, sempre que um tipo construído for instanciado com um tipo de referência como parâmetro, independentemente do tipo, o tempo de execução reutilizará a versão especializada do tipo genérico criada anteriormente.Then, every time that a constructed type is instantiated with a reference type as its parameter, regardless of what type it is, the runtime reuses the previously created specialized version of the generic type. Isso é possível porque todas as referências são do mesmo tamanho.This is possible because all references are the same size.

Por exemplo, suponha que há dois tipos de referência, uma classe Customer e uma classe Order e que uma pilha de tipos Customer foi criada:For example, suppose you had two reference types, a Customer class and an Order class, and also suppose that you created a stack of Customer types:

class Customer { }
class Order { }
Stack<Customer> customers;

Neste ponto, o tempo de execução gerará uma versão especializada da classe Stack<T> que armazenará referências de objeto que serão preenchidas posteriormente, em vez de armazenar dados.At this point, the runtime generates a specialized version of the Stack<T> class that stores object references that will be filled in later instead of storing data. Suponha que a próxima linha de código crie uma pilha de outro tipo de referência, com o nome Order:Suppose the next line of code creates a stack of another reference type, which is named Order:

Stack<Order> orders = new Stack<Order>();

Ao contrário dos tipos de valor, outra versão especializada da classe Stack<T> não será criada para o tipo Order.Unlike with value types, another specialized version of the Stack<T> class is not created for the Order type. Em vez disso, uma instância da versão especializada da classe Stack<T> será criada e a variável orders será definida para referenciá-la.Instead, an instance of the specialized version of the Stack<T> class is created and the orders variable is set to reference it. Imagine que uma linha de código foi encontrada para criar uma pilha de um tipo Customer:Suppose that you then encountered a line of code to create a stack of a Customer type:

customers = new Stack<Customer>();

Assim como acontece com o uso anterior da classe Stack<T> criada usando o tipo Order, outra instância da classe especializada Stack<T> é criada.As with the previous use of the Stack<T> class created by using the Order type, another instance of the specialized Stack<T> class is created. Os ponteiros contidos nela são definidos para referenciar uma área de memória do tamanho de um tipo Customer.The pointers that are contained therein are set to reference an area of memory the size of a Customer type. Como a quantidade de tipos de referência pode variar muito entre os programas, a implementação de genéricos no C# reduz significativamente a quantidade de código ao diminuir para um o número de classes especializadas criadas pelo compilador para classes genéricas ou tipos de referência.Because the number of reference types can vary wildly from program to program, the C# implementation of generics greatly reduces the amount of code by reducing to one the number of specialized classes created by the compiler for generic classes of reference types.

Além disso, quando uma classe genérica do C# for instanciada usando um tipo de valor ou parâmetro de tipo de referência, a reflexão pode consultá-la em tempo de execução e o seu tipo real e parâmetro de tipo podem ser determinados.Moreover, when a generic C# class is instantiated by using a value type or reference type parameter, reflection can query it at runtime and both its actual type and its type parameter can be ascertained.

Consulte tambémSee also