Visão geral dos genéricos no Visual C++
Os genéricos são parametrizados tipos compatíveis com o Common Language Runtime.Um tipo parametrizado é um tipo que é definido com um parâmetro de tipo desconhecido que é especificado quando o genérico é usado.
Por que os genéricos?
C++ oferece suporte a modelos e modelos e genéricos oferecem suporte a tipos parametrizados para criar classes de coleção de tipos.No entanto, os modelos fornecem compilar-parametrização de tempo.Você não pode fazer referência a um assembly que contém uma definição de modelo e criar novas especializações do modelo.Depois de compilado, um modelo de especializado é semelhante a qualquer classe ou método.Em contraste, os genéricos são emitidas na MSIL como um tipo parametrizado conhecido pelo tempo de execução para ser um tipo parametrizado; código fonte que referencia um assembly que contém um tipo genérico pode criar especializações do tipo genérico.Para obter mais informações sobre a comparação dos modelos do Visual C++ e genéricos, consulte Genéricos e modelos (Visual C++).
Funções e tipos genéricos
Tipos de classe, desde que eles são de tipo gerenciado podem ser genéricos.Um exemplo disso pode ser um List classe. O tipo de um objeto na lista seria o tipo de parâmetro.Se for necessário um List classe para muitos tipos diferentes de objetos, antes de genéricos , você pode ter usado um List que leva System::Object como o tipo de item . Mas isso permitiria que qualquer objeto (incluindo objetos do tipo errado) a ser usado na lista.Uma lista como essa seria chamada de uma coleçãode sem tipoclasse. Na melhor das hipóteses, você pode verificar o tipo em tempo de execução e lançar uma exceção.Ou, você pode ter usado um modelo, que perderia a sua qualidade genérica, uma vez compilada em um assembly.Os consumidores do seu assembly podem não criar suas próprias especializações do modelo.Os genéricos permitem que você criar digitado coleção de classes, digamos que List<int> (leitura como "Lista de int") e List<double> ("List of double") que geraria um compilar- erro de tempo se você tentou colocar um tipo que a coleção não foi projetado para aceitar na coleçãotipada.Além disso, esses tipos permanecem genéricos depois que são compilados.
Uma descrição da sintaxe de classes genéricas que pode ser encontrada no Classes genéricas (C + + / CLI). um novo namespace, System.Collections.Generic, apresenta um conjunto de tipos de coleção de parametrizadas incluindo Dictionary<TKey, TValue>, List<T> e LinkedList<T>.Consulte Os genéricos do.NET Framework Class Library (guia de programação do C#) para maiores informações.
Funções de membro declasse de instância e estático, delegados e funções globais também podem ser genéricas. Funções genéricas podem ser necessárias se os parâmetros da funçãode um tipo desconhecido, ou se a função em si deve trabalhar com tipos genéricos.Em muitos casos em que System::Object pode ter sido usado no passado como um parâmetro para um tipo de objeto desconhecido, umparâmetro do tipo genéricopode ser usado em vez disso, permitindo mais tipo -código seguro. Qualquer tentativa de um tipo que a função não foi projetado para passar será sinalizada como um erro em tempo de compilar .Usando System::Object como uma funçãoparâmetro, a transmissão acidental de um objeto que não era deve lidar com a função seria não detectado, e você teria que converter o tipo de objeto desconhecido para um tipo específico no corpo da função e conta para a possibilidade de uma InvalidCastException. Com um genérico, o código que tentar passar um objeto para a função poderia causar um conflito de tipo para que o corpo da função é garantido que têm o tipo correto.
aplicar a mesma beneficia a classes de coleção baseados em genéricos.Classes de coleção no passado usaria System::Object para armazenar os elementos em uma coleção.Inserção de objetos de um tipo que a coleção não foi projetado para não foi sinalizada em tempo de compilar e freqüentemente nem mesmo quando os objetos foram inseridos.Normalmente, um objeto seria convertido para algum outro tipo quando ele foi acessado na coleção.Somente quando a projeção falhou seria do tipo inesperado detectado.Os genéricos resolve esse problema em tempo de compilar , detectando qualquer código que insere um tipo que não corresponda ao (ou implicitamente converter ) o parâmetro do tipo de coleçãogenérica.
Para obter uma descrição da sintaxe, consulte Funções genéricas (C + + / CLI).
Terminologia usada com os genéricos
Parâmetros de tipo
Uma declaração de genérico contém um ou mais tipos desconhecidos, conhecidos como parâmetros de tipo.Parâmetros de tipo recebem um nome que representa o tipo dentro do corpo da declaraçãogenérico.O tipo de parâmetro é usado como um tipo dentro do corpo da declaraçãogenérico.A declaração genérico para a lista <T> contém o tipo de parâmetro t.
Argumentos de tipo
O do tipo de argumento é o tipo real usado no lugar do tipo de parâmetro , quando a genérica é especializada para um tipo específico ou tipos.Por exemplo, int é o tipo de argumento na List<int>.Tipos de valor e identificador são os únicos tipos permitidos em como umargumentodo tipo genérico.
Tipo construído
Um tipo construído a partir de um tipo genérico é conhecido como um construído tipo.Um tipo não é totalmente especificado, como List<T> é um em aberto construído tipo; um tipo totalmente especificado, como List<double>, é um fechado tipo construído ou tipo especializado.Tipos construídos abertos podem ser usados na definição de outros tipos genéricos ou os métodos e não podem ser totalmente especificados até circunscrito genérico é o próprio especificado.Por exemplo, este é um uso de um tipo de em aberto construído como uma classe base para um genérico:
// generics_overview.cpp
// compile with: /clr /c
generic <typename T>
ref class List {};
generic <typename T>
ref class Queue : public List<T> {};
Restrição
Uma restrição é uma restrição sobre os tipos que podem ser usados como um parâmetrode tipo.Por exemplo, uma determinada classe genérica pode aceitar apenas as classes que herdam de uma classede especificada ou implementar uma determinada interface.Para mais informações, consulte Restrições no genérico Digite parâmetros (C + + / CLI).
Tipos de referência e tipos de valor
Tipos de identificadores e tipos de valor podem ser usados como argumentos de tipo.Na definição de genérica, no qual tipo pode ser usado, a sintaxe é que um dos tipos de referência.Por exemplo, o **->**operador . Quando um tipo de valor é usado como o tipo de argumento, o tempo de execução gera código que usa os tipos de valor diretamente, sem conversão boxing os tipos de valor.
Ao usar um tipo de referência como umargumentodo tipo genérico, use a sintaxe de identificador . Ao usar um tipo de valor como umargumentodo tipo genérico, use o nome do tipo diretamente.
// generics_overview_2.cpp
// compile with: /clr
generic <typename T>
ref class GenericType {};
ref class ReferenceType {};
value struct ValueType {};
int main() {
GenericType<ReferenceType^> x;
GenericType<ValueType> y;
}
Parâmetros de tipo
Parâmetros de tipo em uma classe de genéricos são tratados como outros identificadores.No entanto, porque o tipo não é conhecido, há restrições sobre seu uso.Por exemplo, você não pode usar os membros e métodos para o parâmetrode tipo declasse , a menos que o tipo de parâmetro é conhecido para dar suporte a esses membros. Ou seja, para acessar um membro através do parâmetrodo tipo, você deve adicionar o tipo que contém o membro à lista de restrição de tipo parâmetrodo.
// generics_overview_3.cpp
// compile with: /clr
interface class I {
void f1();
void f2();
};
ref struct R : public I {
virtual void f1() {}
virtual void f2() {}
virtual void f3() {}
};
generic <typename T>
where T : I
void f(T t) {
t->f1();
t->f2();
safe_cast<R^>(t)->f3();
}
int main() {
f(gcnew R());
}
Essas restrições aplicar aos operadores também.Um irrestrita tipo genéricodeparâmetro não pode usar o == e != operadores para comparar duas instâncias do tipo parâmetro maiúsculas e minúsculas o tipo não oferece suporte a esses operadores. Essas verificações são necessárias para genéricos, mas não para os modelos, porque genéricos podem ser especializado em tempo de execução com qualquer classe que satisfaça as restrições, quando ele é muito tarde para verificar se o uso de membros inválido .
Uma instância padrão do parâmetro de tipo pode ser criada usando o () operador. Por exemplo:
T t = T();
onde T é um tipo de parâmetro em uma definição de classe ou método genérico, inicializa a variável para seu valor padrão.Se T é uma classe de ref será um ponteiro nulo; Se T é uma classedo valor, o objeto é inicializado para zero.Isso é chamado de um inicializador padrão.