Bagikan melalui


Jenis Terkelola (C++/CLI)

Visual C++ memungkinkan akses ke fitur .NET melalui jenis terkelola, yang menyediakan dukungan untuk fitur runtime bahasa umum dan tunduk pada keuntungan dan batasan runtime.

Jenis Terkelola dan Fungsi utama

Saat Anda menulis aplikasi menggunakan /clr, argumen main() fungsi tidak boleh dari jenis terkelola.

Contoh tanda tangan yang tepat adalah:

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

.NET Framework Setara dengan Jenis Asli C++

Tabel berikut ini memperlihatkan kata kunci untuk jenis Visual C++ bawaan, yang merupakan alias dari jenis yang telah ditentukan sebelumnya di namespace layanan Sistem .

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

Untuk informasi selengkapnya tentang opsi pengkompilasi ke default ke signed char atau unsigned char, lihat /J (Jenis default char adalah unsigned).

Masalah Versi untuk Jenis Nilai yang Disarangkan dalam Jenis Asli

Pertimbangkan komponen rakitan yang ditandatangani (nama kuat) yang digunakan untuk membangun rakitan klien. Komponen berisi jenis nilai yang digunakan dalam klien sebagai jenis untuk anggota serikat asli, kelas, atau array. Jika versi komponen yang akan datang mengubah ukuran atau tata letak jenis nilai, klien harus dikompresi ulang.

Buat keyfile dengan sn.exe (sn -k mykey.snk).

Contoh

Sampel berikut adalah komponennya.

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

Sampel ini adalah klien:

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

Contoh menghasilkan output ini:

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

Komentar

Namun, jika Anda menambahkan anggota lain ke struct S dalam nested_value_types.cpp (misalnya, double d;) dan mengkompilasi ulang komponen tanpa juga mengkompilasi ulang klien, hasilnya adalah pengecualian yang tidak tertangani (dari jenis System.IO.FileLoadException).

Cara menguji kesetaraan

Dalam sampel berikut, pengujian untuk kesetaraan yang menggunakan Ekstensi Terkelola untuk C++ didasarkan pada apa yang dirujuk oleh handel.

Contoh

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

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

IL untuk program ini menunjukkan bahwa nilai pengembalian diimplementasikan dengan menggunakan panggilan ke op_Equality.

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

Cara mendiagnosis dan memperbaiki masalah kompatibilitas perakitan

Ketika versi rakitan yang dirujuk pada waktu kompilasi tidak cocok dengan versi rakitan yang dirujuk saat runtime, berbagai masalah dapat terjadi.

Ketika rakitan dikompilasi, rakitan lain dapat dirujuk dengan #using sintaks. Selama kompilasi, rakitan ini diakses oleh pengkompilasi. Informasi dari rakitan ini digunakan untuk membuat keputusan pengoptimalan.

Namun, jika rakitan yang direferensikan diubah dan dikombinasikan ulang, juga kompilasi ulang rakitan referensi yang bergantung padanya. Jika tidak, rakitan mungkin menjadi tidak kompatibel. Keputusan pengoptimalan yang valid pada awalnya mungkin tidak benar untuk versi rakitan baru. Berbagai kesalahan runtime mungkin terjadi karena ketidaksesuaian ini. Tidak ada pengecualian khusus yang dihasilkan dalam kasus seperti itu. Cara kegagalan dilaporkan pada runtime tergantung pada sifat perubahan kode yang menyebabkan masalah.

Kesalahan ini seharusnya tidak menjadi masalah dalam kode produksi akhir Anda selama seluruh aplikasi dibangun kembali untuk versi produk Anda yang dirilis. Rakitan yang dirilis ke publik harus ditandai dengan nomor versi resmi, yang akan memastikan bahwa masalah ini dihindari. Untuk informasi selengkapnya, lihat Penerapan Versi Rakitan.

Untuk mendiagnosis dan memperbaiki kesalahan ketidaksesuaian

Anda mungkin mengalami pengecualian runtime atau kondisi kesalahan lainnya dalam kode yang mereferensikan rakitan lain. Jika Anda tidak dapat mengidentifikasi penyebab lain, masalahnya mungkin merupakan rakitan yang sudah kedaluarsa.

  1. Pertama, isolasi dan reproduksi pengecualian atau kondisi kesalahan lainnya. Masalah yang terjadi karena pengecualian yang kedaluarsa harus dapat direproduksi.

  2. Periksa tanda waktu rakitan apa pun yang dirujuk dalam aplikasi Anda.

  3. Jika tanda waktu dari rakitan yang dirujuk lebih lambat dari tanda waktu kompilasi terakhir aplikasi Anda, maka aplikasi Anda kedaluarsa. Jika sudah kedaluarsa, kompilasi ulang aplikasi Anda dengan rakitan terbaru, dan edit kode Anda jika perlu.

  4. Jalankan ulang aplikasi, lakukan langkah-langkah yang mereproduksi masalah, dan verifikasi bahwa pengecualian tidak terjadi.

Contoh

Program berikut mengilustrasikan masalah: pertama-tama mengurangi aksesibilitas metode, lalu mencoba mengakses metode tersebut di rakitan lain tanpa kompilasi ulang. Kompilasi changeaccess.cpp terlebih dahulu. Ini adalah rakitan yang dirujuk yang akan berubah. Kemudian kompilasi referencing.cpp. Ini harus berhasil dikompilasi. Selanjutnya, kurangi aksesibilitas metode yang disebut. Kompilasi ulang changeaccess.cpp dengan opsi /DCHANGE_ACCESSpengkompilasi . Ini membuat access_me metode , bukan public, sehingga tidak dapat dipanggil dari luar Test atau protectedturunannya. Tanpa mengolah referencing.exeulang , jalankan ulang aplikasi. Terjadi MethodAccessException .

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

};

Berikut adalah sumber untuk rakitan referensi:

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

Baca juga

Pemrograman .NET dengan C++/CLI (Visual C++)
Interoperabilitas dengan bahasa .NET lainnya (C++/CLI)
Jenis terkelola (C++/CLI)
#using Direktif