Megosztás a következőn keresztül:


Felügyelt típusok (C++/CLI)

A Visual C++ lehetővé teszi a .NET-funkciók elérését felügyelt típusok használatával, amelyek támogatják a közös nyelvi futtatókörnyezet funkcióit, és amelyekre a futtatókörnyezet előnyei és korlátozásai vonatkoznak.

Felügyelt típusok és a fő függvény

Amikor egy alkalmazást ír a /clr használatával, a main() függvény argumentumai nem lehetnek felügyelt típusúak.

A megfelelő aláírás például a következő:

// managed_types_and_main.cpp
// compile with: /clr
int main(int, char*[], char*[]) {}

A .NET-keretrendszer c++ natív típusok megfelelői

Az alábbi táblázat a beépített Visual C++ típusok kulcsszavait mutatja be, amelyek a Rendszer névterében előre definiált típusok aliasai.

Visual C++ típus .NET-keretrendszer típusa
void System.Void
bool System.Boolean
signed char System.SByte
unsigned char System.Byte
wchar_t System.Char
short és signed short System.Int16
unsigned short System.UInt16
int, signed int, longés signed long System.Int32
unsigned int és unsigned long System.UInt32
__int64 és signed __int64 System.Int64
unsigned __int64 System.UInt64
float System.Single
double és long double System.Double

További információ a fordító alapértelmezett signed charunsigned charbeállításáról: /J (Az alapértelmezett char típus unsigned).

Natív típusokba beágyazott értéktípusok verzióproblémái

Fontolja meg egy aláírt (erős névvel rendelkező) összetevő használatát egy kliens szerelvény létrehozásához. Az összetevő olyan értéktípust tartalmaz, amelyet az ügyfél egy natív unió, osztály vagy tömb tagjaként használ. Ha az összetevő egy későbbi verziója módosítja az értéktípus méretét vagy elrendezését, az ügyfelet újra kell állítani.

Hozzon létre egy kulcsfájlt sn.exe (sn -k mykey.snk).

példa

Az alábbi minta mintaként szolgál az alkotóelemhez.

// nested_value_types.cpp
// compile with: /clr /LD
using namespace System::Reflection;
[assembly:AssemblyVersion("1.0.0.*"),
assembly:AssemblyKeyFile("mykey.snk")];

public value struct S {
   int i;
   void Test() {
      System::Console::WriteLine("S.i = {0}", i);
   }
};

Ez a minta az ügyfél:

// nested_value_types_2.cpp
// compile with: /clr
#using <nested_value_types.dll>

struct S2 {
   S MyS1, MyS2;
};

int main() {
   S2 MyS2a, MyS2b;
   MyS2a.MyS1.i = 5;
   MyS2a.MyS2.i = 6;
   MyS2b.MyS1.i = 10;
   MyS2b.MyS2.i = 11;

   MyS2a.MyS1.Test();
   MyS2a.MyS2.Test();
   MyS2b.MyS1.Test();
   MyS2b.MyS2.Test();
}

A példa a következő kimenetet hozza létre:

S.i = 5
S.i = 6
S.i = 10
S.i = 11

Megjegyzések

Ha azonban egy másik tagot hozzáad a struct S a nested_value_types.cpp-hoz (például double d;) és újrafordítja az összetevőt anélkül, hogy az ügyfelet is újrafordítaná, az eredmény egy kezeletlen kivétel (a System.IO.FileLoadException típusú).

Az egyenlőség tesztelése

A következő példában a C++ felügyelt bővítményeit használó egyenlőségi teszt azon alapul, hogy mire hivatkoznak a leírók.

példa

// mcppv2_equality_test.cpp
// compile with: /clr /LD
using namespace System;

bool Test1() {
   String ^ str1 = "test";
   String ^ str2 = "test";
   return (str1 == str2);
}

Az IL ennek a programnak azt mutatja, hogy a visszatérési érték a op_Equality hívással van megvalósítva.

IL_0012:  call       bool [mscorlib]System.String::op_Equality(string, string)

Szerelvénykompatibilitási problémák diagnosztizálása és megoldása

Ha egy szerelvény fordításkor hivatkozott verziója nem egyezik meg a futásidőben hivatkozott szerelvény verziójával, különböző problémák léphetnek fel.

Amikor összeállít egy szerelvényt, más szerelvényekre is hivatkozhat a #using szintaxis. A fordítási folyamat során ezeket a szerelvényeket a kompilátor éri el. Ezekből a szerelvényekből származó információk az optimalizálási döntések meghozatalára szolgálnak.

Ha azonban a hivatkozott szerelvényt módosítják és újrafordítják, az attól függő hivatkozási szerelvényt is újra kell fordítani. Ellenkező esetben előfordulhat, hogy az összeállítások nem kompatibilisek. Előfordulhat, hogy az elsőre érvényes optimalizálási döntések nem lesznek helyesek az új szerelvényverzióhoz. Ezen inkompatibilitások miatt különböző futásidejű hibák léphetnek fel. Ilyen esetekben nincs külön kivétel. A hiba futásidőben történő jelentésének módja a problémát okozó kódmódosítás jellegétől függ.

Ezek a hibák nem jelenthetnek problémát a végső éles kódban mindaddig, amíg a teljes alkalmazást újraépítjük a termék kiadott verziójához. A nyilvánosan kiadott összeállításokat hivatalos verziószámmal kell megjelölni, hogy ezáltal elkerülhetők legyenek a problémák. További információ: Szerelvény verziószámozása.

Kompatibilitási hiba diagnosztizálása és javítása

A kódban futásidejű kivételek vagy más hibafeltételek léphetnek fel, amelyek egy másik szerelvényre hivatkoznak. Ha nem tud más okot azonosítani, előfordulhat, hogy a probléma elavult szerelvény.

  1. Először elkülönítse és reprodukálja a kivételt vagy más hibafeltételt. Az elavult kivétel miatt fellépő problémáknak reprodukálhatónak kell lenniük.

  2. Ellenőrizze az alkalmazásban hivatkozott összeállítások időbélyegét.

  3. Ha a hivatkozott szerelvények időbélyegei későbbiek, mint az alkalmazás legutóbbi fordításának időbélyege, akkor az alkalmazás elavult. Ha elavult az alkalmazás, újrafordítsa azt a legújabb összeállításokkal, és szükség esetén szerkessze a kódot.

  4. Futtassa újra az alkalmazást, hajtsa végre a problémát reprodukáló lépéseket, és ellenőrizze, hogy a kivétel nem fordul-e elő.

példa

A következő program bemutatja a problémát: először csökkenti egy metódus elérhetőségét, majd megpróbálja elérni ezt a metódust egy másik assemblyben újrafordítás nélkül. Először fordítsd le changeaccess.cpp. A hivatkozott összeállítás az, ami meg fog változni. Ezután fordítsa le referencing.cpp. A fordításnak sikeresen le kell fejeződnie. Ezután csökkentse a hívott metódus hozzáférhetőségét. Fordítsa újra a changeaccess.cpp-t a /DCHANGE_ACCESS fordítói beállítással. A access_me metódust protected teszi, és nem public, így nem hívható meg kívülről Test vagy annak származékaiból. Újrafordítás nélkül futtassa újra az alkalmazást referencing.exe. Ez MethodAccessException történik.

// changeaccess.cpp
// compile with: /clr:safe /LD
// After the initial compilation, add /DCHANGE_ACCESS and rerun
// referencing.exe to introduce an error at runtime. To correct
// the problem, recompile referencing.exe

public ref class Test {
#if defined(CHANGE_ACCESS)
protected:
#else
public:
#endif

  int access_me() {
    return 0;
  }

};

A következő a hivatkozott szerelvény forrása:

// referencing.cpp
// compile with: /clr:safe
#using <changeaccess.dll>

// Force the function to be inline, to override the compiler's own
// algorithm.
__forceinline
int CallMethod(Test^ t) {
  // The call is allowed only if access_me is declared public
  return t->access_me();
}

int main() {
  Test^ t = gcnew Test();
  try
  {
    CallMethod(t);
    System::Console::WriteLine("No exception.");
  }
  catch (System::Exception ^ e)
  {
    System::Console::WriteLine("Exception!");
  }
  return 0;
}

Lásd még

.NET-programozás C++/CLI használatával (Visual C++)
Együttműködés más .NET-nyelvekkel (C++/CLI)
Felügyelt típusok (C++/CLI)
#using irányelv