Dela via


Hanterade typer (C++/CLI)

Visual C++ ger åtkomst till .NET-funktioner via hanterade typer, vilket ger stöd för funktioner i den gemensamma språk körningsmiljön och omfattas av förmånerna och begränsningarna för denna miljö.

Hanterade typer och huvudfunktionen

När du skriver ett program med /clr, kan argumenten för main()-funktionen inte vara av en hanterad typ.

Ett exempel på en korrekt signatur är:

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

.NET Framework-motsvarigheter till C++-inbyggda typer

I följande tabell visas nyckelorden för inbyggda Visual C++-typer, som är alias för fördefinierade typer i systemnamnområdet .

Visual C++-typ .NET Framework-typ
void System.Void
bool System.Boolean
signed char System.SByte
unsigned char System.Byte
wchar_t System.Char
short och signed short System.Int16
unsigned short System.UInt16
int, signed int, longoch signed long System.Int32
unsigned int och unsigned long System.UInt32
__int64 och signed __int64 System.Int64
unsigned __int64 System.UInt64
float System.Single
double och long double System.Double

Mer information om kompilatoralternativet som används som standard till signed char eller unsigned char finns i /J.

Versionsproblem för värdetyper kapslade i interna typer

Överväg en signerad sammansättningskomponent (starkt namn) som används för att skapa en klientsammansättning. Komponenten innehåller en värdetyp som används i klienten som typ för en medlem i en intern union, en klass eller en matris. Om en framtida version av komponenten ändrar storlek eller layout för värdetypen måste klienten kompileras om.

Skapa en nyckelfil med sn.exe (sn -k mykey.snk).

Exempel

Exemplet nedan är en komponent.

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

Det här exemplet är klienten:

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

Exemplet genererar följande utdata:

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

Kommentarer

Men om du lägger till en annan medlem i struct S i nested_value_types.cpp (till exempel double d;) och kompilerar om komponenten utan att också kompilera om klienten, är resultatet ett ohanterat undantag (av typen System.IO.FileLoadException).

Så här testar du för likhet

I följande exempel baseras ett likhetstest som använder hanterade tillägg för C++ på vad handtagen refererar till.

Exempel

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

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

IL för det här programmet visar att returvärdet implementeras med hjälp av ett anrop till op_Equality.

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

Så här diagnostiserar och åtgärdar du kompatibilitetsproblem för samlingar

När versionen av en assembly som refereras vid kompilering inte matchar den version av assemblyn som refereras vid körning kan olika problem uppstå.

När en sammansättning kompileras kan andra sammansättningar refereras till med syntaxen #using . Under kompilering används dessa sammansättningar av kompilatorn. Information från dessa sammansättningar används för att fatta optimeringsbeslut.

Men om den refererade sammansättningen ändras och omkompileras, kan du även kompilera om den refererande sammansättningen som är beroende av den. Annars kan sammansättningarna bli inkompatibla. Optimeringsbeslut som var giltiga till en början kanske inte är korrekta för den nya sammansättningsversionen. Olika körningsfel kan uppstå på grund av dessa inkompatibiliteter. Det finns inget specifikt undantag som genereras i sådana fall. Hur felet rapporteras vid körning beror på vilken typ av kodändring som orsakade problemet.

Dessa fel bör inte vara ett problem i den slutliga produktionskoden så länge hela programmet återskapas för den utgivna versionen av produkten. Sammansättningar som släpps till allmänheten bör markeras med ett officiellt versionsnummer, vilket säkerställer att dessa problem undviks. Mer information finns i Versionshantering för sammansättning.

Diagnostisera och åtgärda ett inkompatibilitetsfel

Du kan stöta på körningsundantag eller andra fel i kod som refererar till en annan assembly. Om du inte kan identifiera en annan orsak kan problemet vara en föråldrad komponent.

  1. Först isolerar och återskapar du undantaget eller andra felvillkor. Ett problem som uppstår på grund av ett inaktuellt undantag bör vara reproducerbart.

  2. Kontrollera tidsstämpeln för alla sammansättningar som refereras i ditt program.

  3. Om tidsstämplarna för några refererade sammansättningar är senare än tidsstämpeln för programmets senaste kompilering är programmet inaktuellt. Om det är inaktuellt kan du kompilera om ditt program med de senaste sammansättningarna och redigera koden om det behövs.

  4. Kör programmet igen, utför de steg som återskapar problemet och kontrollera att undantaget inte inträffar.

Exempel

Följande program illustrerar problemet: det minskar först tillgängligheten för en metod och försöker sedan komma åt den metoden i en annan sammansättning utan att kompilera om. Kompilera changeaccess.cpp först. Det är den refererade sammansättningen som kommer att ändras. Sedan kompilera referencing.cpp. Det bör kompileras framgångsrikt. Minska sedan tillgängligheten för den anropade metoden. Kompilera changeaccess.cpp om med kompileringsalternativet /DCHANGE_ACCESS. Det gör access_me metoden protected, snarare än public, så att den inte kan anropas utifrån Test eller dess derivat. Kör programmet igen utan att rekompilera referencing.exe. En MethodAccessException inträffar.

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

};

Här är källan för referenssammansättningen:

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

Se även

.NET-programmering med C++/CLI (Visual C++)
Samverkan med andra .NET-språk (C++/CLI)
Hanterade typer (C++/CLI)
#using direktiv