Udostępnij za pośrednictwem


Typ wyliczenia CLR

Deklaracja i zachowanie tekstów stałych zmienił się z rozszerzenia zarządzane dla języka C++ do Visual C++.

Deklaracja typu wyliczeniowego rozszerzeń zarządzanych jest poprzedzony __value słowa kluczowego.Idea jest odróżnienia macierzystego enum enum CLR, który pochodzi od System::ValueType, zgłaszając analogicznych funkcji.Na przykład:

__value enum e1 { fail, pass };
public __value enum e2 : unsigned short  { 
   not_ok = 1024, 
   maybe, ok = 2048 
};

Nowe elementy składni rozwiązuje problem rozróżniania macierzystego i teksty stałe CLR przez podkreślając istotę klasy te ostatnie raczej niż jego wartość typu korzenie.Jako takie __value słowo kluczowe jest odrzucany, zastąpione parę słowo kluczowe rozmieszczone enum class.Zapewnia to Symetria pary słowo kluczowe deklaracje odniesienia, wartości i klasy interfejsu:

enum class ec;
value class vc;
ref class rc;
interface class ic;

Tłumaczenie pary wyliczenie e1 i e2 w nowe elementy składni wygląda następująco:

enum class e1 { fail, pass };
public enum class e2 : unsigned short { 
   not_ok = 1024,
   maybe, ok = 2048 
};

Z wyjątkiem małych zmian porowata z zachowaniem CLR typu enum został zmieniony na wiele sposobów:

  • Do przodu deklaracji Enum CLR nie jest już obsługiwany.Nie istnieje żadne mapowanie.Po prostu jest on oznaczony jako błąd kompilacji.
__value enum status; // Managed Extensions: ok
enum class status;   // new syntax: error
  • Rozpoznawanie przeciążenie między wbudowanych typów arytmetyczne i Object hierarchia klas została wycofana pomiędzy wersjami językowymi dwóch!Jako efekt uboczny teksty stałe CLR nie są już domyślnie są konwertowane na typy arytmetycznych.

  • W składni nowego wyliczenia CLR utrzymuje własny zakres, który nie jest w przypadku rozszerzeń zarządzanych.Wcześniej moduły wyliczające były widoczne w zakresie zawierającym wyliczenia.Moduły wyliczające są zhermetyzowana w zakresie wyliczenia.

Obiekt rodzaju są CLR tekstów stałych

Rozważmy poniższy fragment kodu:

__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?
}

Dla programisty C++ macierzystego, naturalne odpowiedź na pytanie, których wystąpienia przeciążone f() jest wywoływana, jest f(int).Typ wyliczeniowy jest symboliczne stałą i uczestniczy w standardowych integralnej promocji, które w takim przypadku mają pierwszeństwo przed. I w rzeczywistości w zarządzane rozszerzenia to wystąpienie, do którego rozwiązuje wywołanie.To spowodowane szereg niespodzianek-nie użyliśmy je w macierzystym C++ samopoczucie — ale nam potrzebne do interakcji z istniejących ram BCL (Biblioteka klasy podstawowej), gdzie Enum jest klasą pośrednio pochodną Object.W Visual C++ projekt języka, wystąpienie f() wywoływany jest to, że z f(Object^).

Sposób Visual C++ wybrał wymuszenie to nie obsługuje niejawnej konwersji typu CLR enum i rodzajów arytmetycznych.Oznacza to, że dowolny przydział obiektu CLR typu enum na typ arytmetyczny wymaga jawne rzutowania.Tak więc na przykład, biorąc pod uwagę

void f( int );

jako formę przeciążone w wywołaniu zarządzane rozszerzenia

f( rslt ); // ok: Managed Extensions; error: new syntax

jest ok i wartość zawartą w ramach rslt jest niejawnie konwertowana na wartość całkowitą.W Visual C++, to wywołanie nie można skompilować.Poprawne tłumaczenie go, możemy wstawić operator konwersji:

f( safe_cast<int>( rslt )); // ok: new syntax

Zakres CLR typu tekstu stałego

Jedną ze zmian między w językach C i C++ było dodanie zakresu w obrębie obiektu portowego struct języka C++.W C struct jest po prostu agregacji danych nie obsługują interfejsu lub skojarzonego zakresu.To był dość radykalną zmianę w czasie i jest kwestią sporną dla wielu nowych użytkowników języka C++ pochodzących z języka C.Związek między macierzystym i CLR enum jest analogiczne.

W zarządzanych rozszerzeń podjęto próbę, do definiowania nazw słabo wtryskiwanego dla moduły wyliczające Enum CLR w celu symulacji braku zakresie w macierzystym enum.To okażą się skuteczne.Problem polega na tym, że powoduje to, że moduły wyliczające do wycieku do globalnego obszaru nazw, w wyniku trudno zarządzać konfliktów nazw.W nowych składni możemy dostosowane do innych języków CLR we wspieraniu zakresy w CLR enum.

Oznacza to, że każde niekwalifikowanych korzystanie z modułu wyliczającego CLR enum nie zostanie rozpoznany przez nowe elementy składni.Spójrzmy na przykład rzeczywistych.

// 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)
   }
};

Każdy z trzech bez zastrzeżeń używa nazwy modułu wyliczającego ((1), (2), i (3)) będą musiały być kwalifikowany w tłumaczeniu do nowych składni, aby skompilować kod źródłowy.Oto poprawne tłumaczenie oryginalnego kodu źródłowego:

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)
   }
};

Spowoduje to zmianę strategii projektowania pomiędzy pochodzący i wyliczenia CLR.Z wyliczenia CLR, utrzymanie skojarzonego zakresu w Visual C++, nie jest ani konieczne ani skuteczne do hermetyzacji deklaracji wyliczenia w klasie.Tego języka ewoluował w czasie cfront 2.0 w Bell Laboratories również dla rozwiązania problemu zanieczyszczenia Nazwa globalnego.

W oryginalnej wersji beta nowej biblioteki iostream przez Jerry Schwarz w Bell Laboratories, Jerry nie hermetyzacji wszystkie skojarzone, zdefiniowane dla biblioteki i typowe moduły wyliczające takich jak teksty stałe read, write, append, i tak dalej się to prawie niemożliwe dla użytkowników do kompilowania ich istniejącego kodu.Jednym rozwiązaniem byłby do modyfikacji nazwy, takie jak io_read, io_write, itp. Drugim rozwiązaniem byłby do modyfikacji języka przez dodanie zakresu do wyliczenia, ale nie było to możliwe w tym czasie.Środkowy rozwiązaniem było hermetyzacji enum w obrębie tej klasy lub klas hierarchii, gdzie zarówno nazwa tagu i moduły wyliczające wyliczenia wypełnić zasięgu klasy.) To znaczy motywacji do wprowadzania tekstów stałych w klasach, przynajmniej początkowo, nie było filozoficzne, ale praktyczne odpowiedzi na problem globalnego zanieczyszczenia obszaru nazw.

Z Visual C++ enum, nie ma już żadnych istotnych korzyści dla encapsulating wyliczenia w klasie.W rzeczywistości, jeśli spojrzeć na System obszarów nazw, zobaczysz że teksty stałe, klas i interfejsów zamieszkują w tej samej przestrzeni deklaracji.

Zobacz też

Informacje

Wylicz klasy

Koncepcje

Typy wartości i ich zachowania (C++/CLI)