Tipo de enumeração CLR
A declaração e o comportamento de enums mudou de gerenciado Extensions para C++ para Visual C++ 2008.
A declaração de enum gerenciado Extensions for precedida pela __value palavra-chave. A idéia aqui é distinguir o enum nativo de enum CLR que é derivada de System::ValueType, ao mesmo tempo, sugerindo uma funcionalidade semelhante. Por exemplo:
__value enum e1 { fail, pass };
public __value enum e2 : unsigned short {
not_ok = 1024,
maybe, ok = 2048
};
A nova sintaxe soluciona o problema de distinguir nativo e enums CLR, enfatizando a natureza de classe do último, em vez de suas raízes de tipo de valor.sistema autônomo como a __value palavra-chave é descartado, substituídos por emparelhar de palavra-chave espaçados de enum class. Isso fornece uma simetria de pares de palavra-chave para as declarações de referência, valor e classes de interface:
enum class ec;
value class vc;
ref class rc;
interface class ic;
A tradução do emparelhar de enumeração e1 e e2 em novas aparências de sintaxe da seguinte maneira:
enum class e1 { fail, pass };
public enum class e2 : unsigned short {
not_ok = 1024,
maybe, ok = 2048
};
Além dessa alterar sintática pequena, o comportamento do tipo enum CLR foi alterado de diversas maneiras:
- Não há mais suporte para uma declaração de reenvio de uma enumeração CLR.Não há nenhum mapeamento.Ele simplesmente está sinalizado sistema autônomo um erro em time de compilar.
__value enum status; // Managed Extensions: ok
enum class status; // new syntax: error
A resolução de sobrecarga entre os tipos de aritméticos internos e o Object hierarquia de classes inverteu entre as versões de duas linguagem!sistema autônomo um efeito colateral, enums CLR não implicitamente são convertidos para tipos de aritméticos.
A nova sintaxe um enum CLR mantém seu próprio escopo, que não é o caso de gerenciado Extensions.Anteriormente, os enumeradores eram visíveis dentro do escopo que contém a enumeração.Agora, os enumeradores são encapsulados dentro do escopo de enum.
CLR Enums são um tipo de objeto
Considere o fragmento de código a seguir:
__value enum status { fail, pass };
void f( Object* ){ Console::WriteLine("f(Object)\n"); }
void f( int ){ Console::WriteLine("f(int)\n"); }
int main()
{
status rslt = fail;
f( rslt ); // which f is invoked?
}
Para o programador de C++ nativo, o natural resposta à pergunta de qual instância do sobrecarregado f é invocada é da f(int). Enum é uma constante de integral simbólica e promoções integrais padrão que levam a precedência no caso ela participa.E de fato no gerenciado Extensions isso era a instância para o qual a telefonar resolve.Isso causou um número de surpresas – não quando usá-los em um nativo C++ de espírito – mas, quando precisamos interagir com a estrutura existente de BCL (Base biblioteca de classes), onde um Enum é uma classe indiretamente derivada Object. No Visual C++ 2008 design de linguagem, a instância do f invocada é da f(Object^).
A forma Visual C++ 2008 optou por impor isso é para não suporte para conversões implícitas entre um tipo de enum do CLR e os tipos de aritméticos. Isso significa que qualquer atribuição de um objeto de um tipo enum do CLR para um tipo de aritmético exigirá uma conversão explícita.Assim, por exemplo, dada
void f( int );
sistema autônomo um método sobrecarregado não sistema autônomo extensões gerenciadas, a telefonar
f( rslt ); // ok: Managed Extensions; error: new syntax
é ok e o valor contido em rslt implicitamente é convertido em um valor inteiro. In Visual C++ 2008, essa telefonar falhar compilar. Para traduzi-la corretamente, é necessário inserir um operador de conversão:
f( safe_cast<int>( rslt )); // ok: new syntax
O escopo do tipo Enum CLR
Uma das alterações entre as linguagens C e C++ era a adição em C++ do escopo do recurso de struct.Em C, uma struct é apenas um agregado sem suporte de uma interface ou um escopo associado de dados.Essa foi uma mudança radical na time e era um problema para muitos usuários C++ novos proveniente da linguagem C contenciosos.A relação entre o nativo e do CLR enum é análoga.
No gerenciado Extensions, houve uma tentativa para definir os nomes sem rigidez injetados para os enumeradores de uma enum CLR para simular a ausência de escopo dentro do enum nativo.Isso ser bem-sucedido.O problema é que isso faz com que os enumeradores para entorne no namespace global, resultando em difíceis de gerenciar os conflitos de nome.Na sintaxe de novo, podemos ter conformed às linguagens CLR Outros para oferecer suporte a escopos dentro do CLR enum.
Isso significa que qualquer uso não-qualificado de um enumerador de um enum CLR não será reconhecido pela nova sintaxe.Vejamos um exemplo real.
// Managed Extensions supporting weak injection
__gc class XDCMake {
public:
__value enum _recognizerEnum {
UNDEFINED,
OPTION_USAGE,
XDC0001_ERR_PATH_DOES_NOT_EXIST = 1,
XDC0002_ERR_CANNOT_WRITE_TO = 2,
XDC0003_ERR_INCLUDE_TAGS_NOT_SUPPORTED = 3,
XDC0004_WRN_XML_LOAD_FAILURE = 4,
XDC0006_WRN_NONEXISTENT_FILES = 6,
};
ListDictionary* optionList;
ListDictionary* itagList;
XDCMake() {
optionList = new ListDictionary;
// here are the problems …
optionList->Add(S"?", __box(OPTION_USAGE)); // (1)
optionList->Add(S"help", __box(OPTION_USAGE)); // (2)
itagList = new ListDictionary;
itagList->Add(S"returns",
__box(XDC0004_WRN_XML_LOAD_FAILURE)); // (3)
}
};
Cada um dos três usos não qualificados dos nomes de enumerador ((1), (2), e (3)) precisará ser qualificado na conversão para a nova sintaxe para que o código-fonte compilar. Aqui está uma tradução correta do código-fonte original:
ref class XDCMake {
public:
enum class _recognizerEnum {
UNDEFINED, OPTION_USAGE,
XDC0001_ERR_PATH_DOES_NOT_EXIST = 1,
XDC0002_ERR_CANNOT_WRITE_TO = 2,
XDC0003_ERR_INCLUDE_TAGS_NOT_SUPPORTED = 3,
XDC0004_WRN_XML_LOAD_FAILURE = 4,
XDC0006_WRN_NONEXISTENT_FILES = 6
};
ListDictionary^ optionList;
ListDictionary^ itagList;
XDCMake() {
optionList = gcnew ListDictionary;
optionList->Add("?",_recognizerEnum::OPTION_USAGE); // (1)
optionList->Add("help",_recognizerEnum::OPTION_USAGE); //(2)
itagList = gcnew ListDictionary;
itagList->Add( "returns",
_recognizerEnum::XDC0004_WRN_XML_LOAD_FAILURE); //(3)
}
};
Isso altera a estratégia de design entre um nativo e um enum CLR.Com um enum CLR mantêm um escopo associado em Visual C++ 2008, ele não é necessário nem eficiente encapsular a declaração de enum dentro de uma classe. Este idioma evoluiu perto da time do cfront 2.0 no Bell Laboratories também para solucionar o problema de poluição de nome global.
Na versão beta original da nova biblioteca iostream por Jerry Schwarz na Bell Laboratories, Jerry não encapsular todas sistema autônomo enumerações associadas definidas para a biblioteca e sistema autônomo enumeradores comuns, sistema autônomo read, write, appende assim por diante, tornou quase impossível para sistema autônomo usuários compilar seu código existente. Uma solução teria sido desconfiguram sistema autônomo nomes, sistema autônomo io_read, io_write, etc.. Uma segunda solução seria modificar o linguagem ao adicionar escopo a um enum, mas isso não era practicable no momento.A solução intermediária era encapsular enum dentro da classe ou classe hierarquia, onde o nome de marca e enumeradores do enum popular o escopo de fechamento de classe.) Ou seja, a motivação para o posicionamento de enums nas classes, pelo menos originalmente, não era filosóficas, mas uma resposta prática para o problema de poluição de espaço para nome global.
Com o Visual C++ 2008 Enum, não há qualquer benefício convincente para encapsular um enum dentro de uma classe. Na verdade, se você examinar o System espaços para nomes, você verá que enums, classes e interfaces habitar o mesmo espaço de declaração.
Consulte também
Conceitos
Tipos de valor e seus comportamentos