Pengecualian (C++/CX)
Penanganan kesalahan di C++/CX didasarkan pada pengecualian. Pada tingkat yang paling mendasar, komponen Windows Runtime melaporkan kesalahan sebagai nilai HRESULT. Dalam C++/CX, nilai-nilai ini dikonversi ke pengecualian yang sangat diketik yang berisi nilai HRESULT dan deskripsi string yang dapat Anda akses secara terprogram. Pengecualian diimplementasikan sebagai ref class
yang berasal dari Platform::Exception
. Namespace Platform
mendefinisikan kelas pengecualian yang berbeda untuk nilai HRESULT yang paling umum; semua nilai lain dilaporkan melalui Platform::COMException
kelas . Semua kelas pengecualian memiliki bidang Pengecualian::HResult yang dapat Anda gunakan untuk mengambil HRESULT asli. Anda juga dapat memeriksa informasi tumpukan panggilan untuk kode pengguna di debugger yang dapat membantu menentukan sumber asli pengecualian, bahkan jika itu berasal dari kode yang ditulis dalam bahasa selain C++.
Pengecualian
Dalam program C++ Anda, Anda dapat melempar dan menangkap pengecualian yang berasal dari operasi Windows Runtime, pengecualian yang berasal dari std::exception
, atau jenis yang ditentukan pengguna. Anda harus melemparkan pengecualian Windows Runtime hanya ketika akan melewati batas antarmuka biner aplikasi (ABI), misalnya, ketika kode yang menangkap pengecualian Anda ditulis dalam JavaScript. Ketika pengecualian C++ Non-Windows Runtime mencapai batas ABI, pengecualian diterjemahkan ke dalam Platform::FailureException
pengecualian, yang mewakili E_FAIL HRESULT. Untuk informasi selengkapnya tentang ABI, lihat Membuat Komponen Runtime Windows di C++.
Anda dapat mendeklarasikan Platform::Exception dengan menggunakan salah satu dari dua konstruktor yang mengambil parameter HRESULT, atau parameter HRESULT dan parameter Platform::String^ yang dapat diteruskan di seluruh ABI ke aplikasi Windows Runtime apa pun yang menanganinya. Atau Anda dapat mendeklarasikan pengecualian dengan menggunakan salah satu dari dua kelebihan metode Exception::CreateException yang mengambil parameter HRESULT, atau parameter HRESULT dan Platform::String^
parameter.
Pengecualian standar
C++/CX mendukung serangkaian pengecualian standar yang mewakili kesalahan HRESULT biasa. Setiap pengecualian standar berasal dari Platform::COMException, yang pada gilirannya berasal dari Platform::Exception
. Ketika Anda melemparkan pengecualian di seluruh batas ABI, Anda harus melemparkan salah satu pengecualian standar.
Anda tidak dapat memperoleh jenis pengecualian Anda sendiri dari Platform::Exception
. Untuk melempar pengecualian kustom, gunakan HRESULT yang ditentukan pengguna untuk membuat COMException
objek.
Tabel berikut mencantumkan pengecualian standar.
Nama | HRESULT yang mendasar | Deskripsi |
---|---|---|
COMException | hresult yang ditentukan pengguna | Dilemparkan ketika HRESULT yang tidak dikenal dikembalikan dari panggilan metode COM. |
AccessDeniedException | E_ACCESSDENIED | Dilemparkan saat akses ditolak ke sumber daya atau fitur. |
ChangedStateException | E_CHANGED_STATE | Dilemparkan ketika metode iterator koleksi atau tampilan koleksi dipanggil setelah koleksi induk berubah, sehingga membatalkan hasil metode. |
ClassNotRegisteredException | REGDB_E_CLASSNOTREG | Dilemparkan ketika kelas COM belum terdaftar. |
DisconnectedException | RPC_E_DISCONNECTED | Dilemparkan ketika objek terputus dari kliennya. |
FailureException | E_FAIL | Dilemparkan ketika operasi gagal. |
InvalidArgumentException | E_INVALIDARG | Dilemparkan ketika salah satu argumen yang disediakan untuk metode tidak valid. |
InvalidCastException | E_NOINTERFACE | Dilemparkan ketika jenis tidak dapat dilemparkan ke jenis lain. |
NotImplementedException | E_NOTIMPL | Dilemparkan jika metode antarmuka belum diimplementasikan pada kelas. |
NullReferenceException | E_POINTER | Dilemparkan ketika ada upaya untuk membatalkan referensi referensi objek null. |
ObjectDisposedException | RO_E_CLOSED | Dilemparkan ketika operasi dilakukan pada objek yang dibuang. |
OperationCanceledException | E_ABORT | Dilemparkan ketika operasi dibatalkan. |
OutOfBoundsException | E_BOUNDS | Dilemparkan ketika operasi mencoba mengakses data di luar rentang yang valid. |
OutOfMemoryException | E_OUTOFMEMORY | Dilemparkan ketika tidak ada cukup memori untuk menyelesaikan operasi. |
WrongThreadException | RPC_E_WRONG_THREAD | Dilemparkan ketika utas memanggil melalui penunjuk antarmuka yang untuk objek proksi yang bukan milik apartemen utas. |
Properti HResult dan Pesan
Semua pengecualian memiliki properti HResult dan properti Pesan . Properti Exception::HResult mendapatkan nilai HRESULT numerik yang mendasar pengecualian. Properti Exception::Message mendapatkan string yang disediakan sistem yang menjelaskan pengecualian. Di Windows 8, pesan hanya tersedia di debugger dan bersifat baca-saja. Ini berarti Bahwa Anda tidak dapat mengubahnya ketika Anda menumbuhkan kembali pengecualian. Di Windows 8.1, Anda dapat mengakses string pesan secara terprogram dan memberikan pesan baru jika Anda menggagalkan kembali pengecualian. Informasi callstack yang lebih baik juga tersedia di debugger, termasuk callstack untuk panggilan metode asinkron.
Contoh
Contoh ini menunjukkan cara melempar pengecualian Windows Runtime untuk operasi sinkron:
String^ Class1::MyMethod(String^ argument)
{
if (argument->Length() == 0)
{
auto e = ref new Exception(-1, "I'm Zork bringing you this message from across the ABI.");
//throw ref new InvalidArgumentException();
throw e;
}
return MyMethodInternal(argument);
}
Contoh berikutnya menunjukkan cara menangkap pengecualian.
void Class2::ProcessString(String^ input)
{
String^ result = nullptr;
auto obj = ref new Class1();
try
{
result = obj->MyMethod(input);
}
catch (/*InvalidArgument*/Exception^ e)
{
// Handle the exception in a way that's appropriate
// for your particular scenario. Assume
// here that this string enables graceful
// recover-and-continue. Why not?
result = ref new String(L"forty two");
// You can use Exception data for logging purposes.
Windows::Globalization::Calendar calendar;
LogMyErrors(calendar.GetDateTime(), e->HResult, e->Message);
}
// Execution continues here in both cases.
//#include <string>
std::wstring ws(result->Data());
//...
}
Untuk menangkap pengecualian yang dilemparkan selama operasi asinkron, gunakan kelas tugas dan tambahkan kelanjutan penanganan kesalahan. Pengecualian kelanjutan penanganan kesalahan marshal yang dilemparkan pada utas lain kembali ke utas panggilan sehingga Anda dapat menangani semua pengecualian potensial hanya pada satu titik dalam kode Anda. Untuk informasi selengkapnya, lihat Pemrograman Asinkron di C++.
Peristiwa UnhandledErrorDetected
Di Windows 8.1 Anda dapat berlangganan peristiwa statis Windows::ApplicationModel::Core::CoreApplication::UnhandledErrorDetected , yang menyediakan akses ke kesalahan yang tidak tertangani yang akan menurunkan proses. Terlepas dari asal kesalahan, kesalahan mencapai handler ini sebagai objek Windows::ApplicationModel::Core::UnhandledError yang diteruskan dengan arg peristiwa. Saat Anda memanggil Propagate
objek, objek akan membuat dan melempar Platform::*Exception
jenis yang sesuai dengan kode kesalahan. Dalam blok tangkapan, Anda dapat menyimpan status pengguna jika perlu dan kemudian mengizinkan proses untuk dihentikan dengan memanggil throw
, atau melakukan sesuatu untuk membuat program kembali ke keadaan yang diketahui. Contoh berikut menunjukkan pola dasar:
Di app.xaml.h:
void OnUnhandledException(Platform::Object^ sender, Windows::ApplicationModel::Core::UnhandledErrorDetectedEventArgs^ e);
Dalam app.xaml.cpp:
// Subscribe to the event, for example in the app class constructor:
Windows::ApplicationModel::Core::CoreApplication::UnhandledErrorDetected += ref new EventHandler<UnhandledErrorDetectedEventArgs^>(this, &App::OnUnhandledException);
// Event handler implementation:
void App::OnUnhandledException(Platform::Object^ sender, Windows::ApplicationModel::Core::UnhandledErrorDetectedEventArgs^ e)
{
auto err = e->UnhandledError;
if (!err->Handled) //Propagate has not been called on it yet.
{
try
{
err->Propagate();
}
// Catch any specific exception types if you know how to handle them
catch (AccessDeniedException^ ex)
{
// TODO: Log error and either take action to recover
// or else re-throw exception to continue fail-fast
}
}
Keterangan
C++/CX tidak menggunakan finally
klausa.