Sdílet prostřednictvím


Výčtový typ CLR

Prohlášení a chování výčty změnila z spravované rozšíření c++ k Visual C++ 2010.

Deklarace výčtu spravovaného rozšíření předchází __value klíčové slovo. Zde je výčet nativní odlišit od CLR výčtu, který je odvozen z System::ValueType, při návrhu obdobné funkce. Příklad:

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

Novou syntaxi řeší problém rozlišování nativní a výčty CLR ve zdůraznění povahy ten spíše než jeho kořeny hodnotu typu třídy. Jako takové __value je zahozen klíčového slova nahrazena pár rozmístěných klíčové slovo enum class. To poskytuje symetrie dvojice klíčové slovo deklarací odkaz, hodnota a rozhraní třídy:

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

Překlad výčtu pár e1 a e2 novou syntaxi vypadá takto:

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

Kromě této malé syntaktické změny, se chování CLR výčtového typu změnilo v mnoha způsobech:

  • Dopředná deklarace CLR výčtového typu již není nadále podporována. Neexistuje mapování. Jednoduše označen jako chyba při kompilaci.
__value enum status; // Managed Extensions: ok
enum class status;   // new syntax: error
  • Rozlišení mezi aritmetické předdefinované typy přetížení a Object mezi dvě jazykové verze byla stornována hierarchie třídy! Vedlejším účinkem je to, že CLR výčtové typy již nejsou implicitně převáděny na aritmetické typy.

  • V nové syntaxi urdžuje CLR výčtový typ vlastní rozsah, což není případem spravovaného rozšíření. Dříve byly viditelné v rámci obsahující výčtu čítače výčtů. Nyní čítače výčtů jsou zapouzdřeny v rámci výčtu.

Objekt typu jsou výčty CLR

Zvažte následující fragment kódu:

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

Pro nativní C++ programmer fyzické odpověď na otázku která instance přetížená f() je vyvolána, je f(int). Enum je symbolický integrální konstanta a účastní standardní nedílnou propagační akce, které v tomto případě přednost. A ve skutečnosti v rozšíření spravované instance, které řeší volání. Příčinou mnoha překvapení – není při jejich použití nativní C++ rámec o Nezapomeňte – ale potřebujeme jejich používání stávajícího rámce BCL (Knihovna třídy Base) kde Enum je třída nepřímo odvozené z Object. V Visual C++ 2010 Návrh jazyka, instance f() , vyvolat je f(Object^).

Způsob Visual C++ 2010 zvolil vynutit je nepodporují implicitní převody mezi výčtového typu CLR a typy aritmetické, To znamená, že přiřazení výčtového typu CLR aritmetické typu objektu bude vyžadovat explicitní přetypování. Takže například uveden

void f( int );

jako metoda přetížený, spravované rozšíření volání

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

ok a hodnoty obsažené v rslt implicitně převeden na celočíselnou hodnotu. V Visual C++ 2010, toto volání selže kompilace. Správně převáděl ji můžeme třeba vložit operátor převodu:

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

Obor výčtového typu CLR

Některé změny mezi jazyky c a C++ byla přídavek obor v rámci facility struktura v jazyce C++. Struktura v c je pouze data bez podpory rozhraní nebo přidružené oboru agregační. To byl poměrně k radikální změně v době a sporné problém mnoho nových uživatelů C++ pocházející z jazyka C. Vztah mezi nativní a výčet CLR je analogická.

V rozšíření spravované proběhl pokus definování názvů slabě vloženého čítače výčtů enum CLR k simulaci absence obor v rámci nativní enum. To nemusí být úspěšná. Problém je, že to způsobuje čítače výčtů do přepadového do globální obor názvů výsledkem obtížně Kolize názvů. Nová syntaxe jsme mít úprava CLR jazyky v doprovodné obory CLR enum.

To znamená, že použití neúplný výčet CLR enum bude rozpoznána novou syntaxi. Podívejme se například reálného světa.

// 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ždé tři neúplný výčet názvů používá ((1), (2), a (3)) bude nutné kvalifikací v překladu novou syntaxi, aby zdrojový kód a kompilace. Zde je správný překlad původního zdrojového kódu:

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

Změní se návrh strategie mezi rodák a výčet CLR. S CLR enum udržování spojena obor v Visual C++ 2010, není nutné ani účinné zapouzdřit prohlášení v rámci třída výčtu Tento idiomu evolved v době cfront 2.0 v rámci laboratoře Bell také na název globálního znečišťování problém vyřešit.

V původní verzi beta nové knihovny iostream podle Jerry Schwarz v laboratořích Bell Jerry zapouzdřit přidružené výčty definované pro knihovny a společné čítače výčtu jako read, write, appenda podobně znemožnila téměř uživatelům kompilovat jejich stávající kód Jedním z řešení by byla mangle názvy, jako například io_read, io_writeatd. Druhé řešení by byl jazyk změnit přidáním oboru enum, ale to nebylo možné v době. Střední roztok byl zapouzdřit enum ve třídě nebo třídy hierarchii, kde název značky a čítače výčtů výčtu naplnit ohraničující třídy oboru.) Motivace pro uvedení výčty v rámci tříd, alespoň původně byl, filozofické, ale praktické odpověď na problém znečišťování globální obor názvů.

S Visual C++ 2010 enum již není žádné přesvědčivé výhodu encapsulating enum v rámci třída Ve skutečnosti podíváte System obory názvů, uvidíte, že výčty, tříd a rozhraní všech obývající stejné místo prohlášení.

Viz také

Odkaz

enum class

Koncepty

Typy hodnot a jejich chování