Baca dalam bahasa Inggris

Bagikan melalui


Pengantar Microsoft Interface Definition Language 3.0

Microsoft Interface Definition Language (MIDL) 3.0 adalah sintaks modern yang disederhanakan untuk menentukan jenis Windows Runtime di dalam file Bahasa Definisi Antarmuka (IDL) ( file.idl). Sintaks baru ini akan terasa akrab bagi siapa pun yang berpengalaman dengan C, C++, C#, dan/atau Java. MIDL 3.0 adalah cara yang sangat nyaman untuk menentukan kelas runtime C++/WinRT, secara dramatis lebih ringkas daripada versi IDL sebelumnya (mengurangi desain dengan panjang dua pertiga, dan menggunakan default yang wajar untuk mengurangi kebutuhan dekorasi dengan atribut).

Berikut tampilan MIDL 3.0; contoh ini menunjukkan sebagian besar elemen sintaks bahasa yang kemungkinan akan Anda gunakan.

// Photo.idl
namespace PhotoEditor
{
    delegate void RecognitionHandler(Boolean arg); // delegate type, for an event.

    runtimeclass Photo : Windows.UI.Xaml.Data.INotifyPropertyChanged // interface.
    {
        Photo(); // constructors.
        Photo(Windows.Storage.StorageFile imageFile);

        String ImageName{ get; }; // read-only property.
        Single SepiaIntensity; // read-write property.

        Windows.Foundation.IAsyncAction StartRecognitionAsync(); // (asynchronous) method.

        event RecognitionHandler ImageRecognized; // event.
    }
}

Perhatikan bahwa sintaks MIDL 3.0 dirancang khusus untuk menentukan jenis. Anda akan menggunakan bahasa pemrograman yang berbeda untuk menerapkan jenis tersebut. Untuk menggunakan MIDL 3.0, Anda memerlukan Windows SDK versi 10.0.17134.0 (Windows 10, versi 1803) (midl.exe versi 8.01.0622 atau yang lebih baru, digunakan dengan sakelar /winrt).

Catatan

Lihat juga referensi terkonsolidasi Windows Runtime (sistem jenis Windows Runtime, dan file Metadata Windows).

MIDL 1.0, 2.0, dan 3.0

Bahasa Definisi Antarmuka (IDL) dimulai dengan sistem Lingkungan Komputasi Terdistribusi/Panggilan Prosedur Jarak Jauh (DCE/RPC). MIDL 1.0 asli adalah DCE/RPC IDL dengan penyempurnaan untuk menentukan antarmuka dan kolase COM.

Sintaks MIDL 2.0 yang diperbarui (juga dikenal sebagai MIDLRT) kemudian dikembangkan dalam Microsoft untuk mendeklarasikan API Windows Runtime untuk platform Windows. Jika Anda melihat di folder Windows SDK %WindowsSdkDir%Include<WindowsTargetPlatformVersion>\winrt maka Anda akan melihat contoh file .idl yang ditulis dengan sintaks MIDL 2.0. Ini adalah API Windows Runtime bawaan, dinyatakan dalam bentuk antarmuka biner aplikasi (ABI) mereka. File-file ini terutama ada untuk digunakan alat—Anda tidak akan menulis atau menggunakan API ini dalam bentuk ini (kecuali Anda menulis kode tingkat yang sangat rendah).

Lihat juga transisi ke MIDL 3.0 dari midlrt klasik.

MIDL 3.0 adalah sintaksis yang jauh lebih sederhana dan lebih modern, yang tujuannya adalah untuk mendeklarasikan WINDOWS Runtime API. Dan Anda dapat menggunakannya dalam proyek Anda, terutama untuk menentukan kelas runtime C++/WinRT. Header, untuk digunakan dari C++/WinRT, untuk API Windows Runtime bawaan adalah bagian dari SDK, di dalam folder %WindowsSdkDir%Include<WindowsTargetPlatformVersion>\cppwinrt\winrt.

Kasus penggunaan untuk MIDL 3.0

Secara umum, semua WINDOWS Runtime API dirancang untuk tersedia untuk semua proyeksi bahasa Windows Runtime. Ini dilakukan, sebagian, dengan memilih untuk secara eksklusif meneruskan jenis Windows Runtime ke dan dari Windows Runtime API. Meskipun ini adalah keputusan desain yang valid untuk meneruskan antarmuka COM mentah ke dan dari Windows Runtime API, melakukannya membatasi konsumen dari Windows Runtime API tertentu ke aplikasi C++. Teknik ini dapat dilihat dalam skenario interoperabilitas—misalnya, saat mengoperasikan antara Direct3D dan XAML. Karena Direct3D ada dalam gambar, skenario selalu dipersempit ke aplikasi C++. Jadi, API yang memerlukan antarmuka COM tidak memberlakukan batasan tambahan apa pun atas dan di atas apa yang melekat. Misalnya, aplikasi C++ dapat memperoleh penunjuk antarmuka IDXGISwapChain , lalu meneruskan ke metode ISwapChainPanelNative::SetSwapChain. Aplikasi C#, misalnya, tidak akan dapat memperoleh IDXGISwapChain untuk memulai, sehingga tidak akan dapat menggunakan metode tersebut karena alasan itu. Pengecualian terkait interop ini hidup di header interop, seperti windows.ui.xaml.media.dxinterop.h.

Jika ada fitur atau fungsionalitas komponen COM yang ingin Anda ekspos ke proyeksi bahasa Windows Runtime di luar C++, kemudian Anda dapat membuat komponen C++ Windows Runtime (WRC) yang secara langsung membuat dan menggunakan komponen COM (seperti DirectX, misalnya), dan mengekspos replikasi beberapa subset fitur dan fungsionalitasnya dalam bentuk permukaan Windows Runtime API yang mengambil dan mengembalikan Windows Jenis runtime saja. Anda kemudian dapat menggunakan WRC tersebut dari aplikasi yang ditulis dalam proyeksi bahasa Windows Runtime apa pun.

Struktur definisi, dan memanggil midl.exe dari baris perintah

Konsep organisasi utama dalam definisi MIDL 3.0 adalah namespace, jenis, dan anggota. File sumber MIDL 3.0 (file .idl) berisi setidaknya satu namespace, di dalamnya adalah jenis dan/atau namespace subordinat. Setiap jenis berisi nol atau lebih anggota.

  • Kelas, antarmuka, struktur, dan enumerasi adalah jenis.
  • Metode, properti, peristiwa, dan bidang adalah contoh anggota.

Saat Anda mengkompilasi file sumber MIDL 3.0, pengkompilasi (midl.exe) memancarkan file metadata Windows Runtime (biasanya file .winmd).

// Bookstore.idl
namespace Bookstore
{
    runtimeclass BookSku : Windows.UI.Xaml.Data.INotifyPropertyChanged
    {
        BookSku();
        BookSku(Single price, String authorName, String coverImagePath, String title);

        Single Price;

        String AuthorName{ get; };
        Windows.UI.Xaml.Media.ImageSource CoverImage{ get; };
        String CoverImagePath{ get; };
        String Title{ get; };

        Boolean Equals(BookSku other);
        void ApplyDiscount(Single percentOff);
    }
}

Karena namespace jenis Windows Runtime menjadi bagian dari nama jenis, contoh di atas mendefinisikan kelas runtime bernama Bookstore.BookSku. Tidak ada cara independen bahasa untuk mengekspresikan BookSku tanpa juga mengekspresikan namespace.

Kelas ini mengimplementasikan antarmuka Windows.UI.Xaml.Data.INotifyPropertyChanged. Dan kelas berisi beberapa anggota: dua konstruktor, properti baca-tulis (Price), beberapa properti baca-saja (AuthorName melaluiJudul ), dan dua metode, bernama Equals dan ApplyDiscount . Perhatikan penggunaan jenis Tunggal daripadafloat . Dan String memiliki huruf besar "S".

Tip

Visual Studio memberikan pengalaman terbaik untuk mengkompilasi MIDL 3.0, melalui C++/WinRT Visual Studio Extension (VSIX). Lihat dukungan Visual Studio untuk C++/WinRT, dan VSIX.

Tetapi Anda juga dapat mengkompilasi MIDL 3.0 dari baris perintah. Jika kode sumber untuk contoh ini disimpan dalam file bernama Bookstore.idl, maka Anda dapat mengeluarkan perintah di bawah ini. Jika perlu untuk kasus Anda, Anda dapat memperbarui nomor versi SDK yang digunakan dalam perintah (yaitu 10.0.17134.0).

midl /winrt /metadata_dir "%WindowsSdkDir%References\10.0.17134.0\windows.foundation.foundationcontract\3.0.0.0" /h "nul" /nomidl /reference "%WindowsSdkDir%References\10.0.17134.0\Windows.Foundation.FoundationContract\3.0.0.0\Windows.Foundation.FoundationContract.winmd" /reference "%WindowsSdkDir%References\10.0.17134.0\Windows.Foundation.UniversalApiContract\6.0.0.0\Windows.Foundation.UniversalApiContract.winmd" /reference "%WindowsSdkDir%\References\10.0.17134.0\Windows.Networking.Connectivity.WwanContract\2.0.0.0\Windows.Networking.Connectivity.WwanContract.winmd" Bookstore.idl

Alat midl.exe mengkompilasi contoh dan menghasilkan file metadata bernama Bookstore.winmd (secara default, nama file .idl digunakan).

Tip

Jika Anda menggunakan lebih dari satu file IDL (untuk saran tentang itu, lihat Kelas runtime Factoring ke dalam file Midl (.idl)), lalu gabungkan semua file .winmd yang dihasilkan ke dalam satu file dengan nama yang sama dengan namespace root. File .winmd akhir tersebut akan menjadi file yang akan dirujuk oleh konsumen API Anda.

Dalam hal ini, BookSku adalah satu-satunya kelas runtime di namespace Bookstore, jadi kami menyimpan langkah dan hanya memberi nama file untuk namespace.

Kebetulan, Anda dapat menggunakan perintah where untuk mengetahui di mana midl.exe diinstal.

where midl

Jika Anda ingin menggunakan jenis yang ditentukan dalam satu file .idl dari file .idl yang berbeda, maka Anda menggunakan direktif import. Untuk detail selengkapnya, dan contoh kode, lihat kontrol XAML ; ikat ke properti C++/WinRT. Tentu saja, jika Anda menggunakan komponen bawaan atau pihak ketiga, Maka Anda tidak akan memiliki akses ke file .idl. Misalnya, Anda mungkin ingin menggunakan Win2D Windows Runtime API untuk penyajian grafis 2D mode langsung. Perintah di atas menggunakan sakelar /reference untuk mereferensikan file metadata Windows Runtime (.winmd). Dalam contoh berikutnya ini, kita akan menggunakan sakelar itu lagi, membayangkan skenario di mana kita memiliki Bookstore.winmd, tetapi tidak Bookstore.idl.

// MVVMApp.idl
namespace MVVMApp
{
    runtimeclass ViewModel
    {
        ViewModel();
        Bookstore.BookSku BookSku{ get; };
    }
}

Jika kode sumber untuk contoh di atas disimpan dalam file bernama MVVMApp.idl, maka Anda dapat mengeluarkan perintah di bawah ini untuk mereferensikan Bookstore.winmd.

midl /winrt /metadata_dir "%WindowsSdkDir%References\10.0.17134.0\windows.foundation.foundationcontract\3.0.0.0" /h "nul" /nomidl /reference "%WindowsSdkDir%References\10.0.17134.0\Windows.Foundation.FoundationContract\3.0.0.0\Windows.Foundation.FoundationContract.winmd" /reference "%WindowsSdkDir%References\10.0.17134.0\Windows.Foundation.UniversalApiContract\6.0.0.0\Windows.Foundation.UniversalApiContract.winmd" /reference "%WindowsSdkDir%\References\10.0.17134.0\Windows.Networking.Connectivity.WwanContract\2.0.0.0\Windows.Networking.Connectivity.WwanContract.winmd" /reference Bookstore.winmd MVVMApp.idl

Namespace

Namespace diperlukan. Ini mengawali nama semua jenis yang ditentukan dalam cakupan blok namespace dengan nama namespace. Namespace juga dapat berisi deklarasi namespace subordinat. Nama jenis yang ditentukan dalam cakupan namespace subordinat memiliki awalan semua nama namespace yang berisi.

Contoh di bawah ini adalah dua cara untuk mendeklarasikan kelas Windows.Foundation.Uri yang sama (seperti yang Anda lihat, titik memisahkan tingkat namespace berlapis).

namespace Windows.Foundation
{
    runtimeclass Uri : IStringable
    {
        ...
    }
}
namespace Windows
{
    namespace Foundation
    {
        runtimeclass Uri : IStringable
        {
            ...
        }
    }
}

Berikut adalah contoh lain yang menunjukkan bahwa legal untuk mendeklarasikan namespace layanan dan jenisnya dengan cara berlapis.

namespace RootNs.SubNs1
{
    runtimeclass MySubNs1Class
    {
        void DoWork();
    }

    namespace SubNs2
    {
        runtimeclass MySubNs2Class
        {
            void DoWork();
        }
    }
}

Tetapi praktik yang lebih umum untuk menutup namespace sebelumnya, dan membuka yang baru, seperti ini.

namespace RootNs.SubNs1
{
    runtimeclass MySubNs1Class
    {
        void DoWork();
    }
}

namespace RootNs.SubNs1.SubNs2
{
    runtimeclass MySubNs2Class
    {
        void DoWork();
    }
}

Jenis

Ada dua jenis data di MIDL 3.0: jenis nilai, dan jenis referensi. Variabel jenis nilai secara langsung berisi datanya. Variabel jenis referensi menyimpan referensi ke datanya (variabel seperti itu juga dikenal sebagai objek ).

Dimungkinkan untuk dua variabel jenis referensi untuk mereferensikan objek yang sama. Dengan demikian, operasi pada satu variabel memengaruhi objek yang dirujuk oleh variabel lain. Dengan jenis nilai, variabel masing-masing memiliki salinan data mereka sendiri, dan tidak dimungkinkan bagi operasi pada satu untuk memengaruhi yang lain.

Jenis nilai MIDL 3.0 selanjutnya dibagi menjadi jenis sederhana, jenis enum, jenis struct, dan jenis nullable.

Jenis referensi MIDL 3.0 dibagi lebih lanjut menjadi jenis kelas, jenis antarmuka, dan jenis delegasi.

Berikut adalah gambaran umum sistem jenis MIDL 3.0. Tidak seperti versi MIDL sebelumnya, Anda tidak dapat menggunakan alias untuk jenis ini.

Golongan Deskripsi
Jenis nilai Jenis sederhana Integral yang ditandatangani: Int16, Int32, Int64
Integral yang tidak ditandatangani: UInt8, UInt16, UInt32, UInt64
Karakter Unicode: Char (mewakili UTF-16LE; unit kode Unicode 16-bit)
String Unicode: String
Titik mengambang IEEE: Tunggal , Ganda
Boolean: Boolean
UUID 128 bit: Guid
Jenis enum Jenis formulir yang ditentukan pengguna enum E {...}
Jenis struktur Jenis formulir yang ditentukan pengguna struct S {...}
Jenis yang dapat diubah ke null Ekstensi dari semua jenis nilai lainnya dengan nilai null
Jenis referensi Jenis kelas Kelas dasar utama dari semua jenis lainnya: Object
Jenis formulir yang ditentukan pengguna runtimeclass C {...}
Jenis antarmuka Jenis formulir yang ditentukan pengguna antarmuka I {...}
Mendelegasikan jenis Jenis formulir yang ditentukan pengguna mendelegasikan < returnType> D(...)

Tujuh jenis integral memberikan dukungan untuk data yang tidak ditandatangani 8-bit; dan nilai 16-bit, 32-bit, dan 64-bit dalam formulir yang ditandatangani atau tidak ditandatangani.

Dua jenis titik mengambang, format Tunggal dan Double, mewakili data menggunakan presisi tunggal 32-bit dan format IEEE 754 presisi Ganda 64-bit.

Jenis Boolean MIDL 3.0 mewakili nilai boolean; baik atau .

Karakter dan string di MIDL 3.0 berisi karakter Unicode. Jenis Char mewakili unit kode UTF-16LE; dan jenis String mewakili urutan unit kode UTF-16LE.

Tabel berikut ini meringkas jenis numerik MIDL 3.0.

Golongan Bit Jenis Rentang/Presisi
Integral yang ditandatangani 16 Int16 –32,768...32,767
32 Int32 –2,147,483,648...2,147,483,647
64 Int64 –9,223,372,036,854,775,808...9,223,372,036,854,775,807
Integral yang tidak ditandatangani 8 UInt8 0...255
16 UInt16 0...65,535
32 UInt32 0...4,294,967,295
64 UInt64 0...18,446,744,073,709,551,615
Titik mengambang 32 Tunggal 1,5 × 10−45 hingga 3,4 × 1038, presisi 7 digit
64 Ganda 5,0 × 10−324 hingga 1,7 × 10308, presisi 15 digit

File sumber MIDL 3.0 menggunakan definisi jenis untuk membuat jenis baru. Definisi jenis menentukan nama dan anggota jenis baru. Kategori jenis MIDL 3.0 ini dapat difinisikan pengguna.

  • jenis atribut,
  • jenis struct,
  • jenis antarmuka,
  • jenis runtimeclass,
  • mendelegasikan jenis, dan
  • jenis enum.

Jenis atribut menentukan atribut Windows Runtime yang dapat diterapkan ke definisi jenis lainnya. Atribut menyediakan metadata tentang jenis yang atributnya diterapkan.

Jenis struct menentukan struktur Windows Runtime yang berisi anggota data (bidang). Struktur adalah jenis nilai, dan tidak memerlukan alokasi timbunan. Anggota data dari jenis struct harus berupa jenis nilai atau jenis yang dapat diubah ke null. Jenis struct tidak mendukung pewarisan.

Jenis antarmuka mendefinisikan antarmuka Windows Runtime, yang merupakan sekumpulan anggota fungsi bernama. Antarmuka dapat menentukan bahwa implementasi antarmuka juga harus menerapkan satu atau beberapa antarmuka tambahan (wajib) yang ditentukan. Setiap jenis antarmuka langsung berasal dari Antarmuka Windows Runtime IInspectable.

Jenis runtimeclass menentukan kelas Windows Runtime (kelas runtime). Kelas runtime berisi anggota yang dapat berupa properti, metode, dan peristiwa.

Delegasi jenis menentukan delegasi Windows Runtime, yang mewakili referensi ke metode dengan daftar parameter tertentu dan jenis pengembalian. Delegasi memungkinkan untuk memperlakukan metode sebagai entitas yang dapat diteruskan sebagai parameter. Delegasi mirip dengan konsep penunjuk fungsi yang ditemukan dalam beberapa bahasa lain. Tidak seperti penunjuk fungsi, delegasi berorientasi objek, dan jenis aman.

Jenis enum adalah jenis yang berbeda dengan konstanta bernama. Setiap jenis enum memiliki jenis implisit yang mendasar; baik Int32 atau UInt32. Sekumpulan nilai jenis enum sama dengan sekumpulan nilai jenis yang mendasar.

MIDL 3.0 mendukung tiga kategori jenis tambahan.

  • jenis array dimensi tunggal,
  • jenis nilai nullable, dan
  • jenis Objek .

Anda tidak perlu mendeklarasikan array dimensi tunggal sebelum Anda dapat menggunakannya. Sebagai gantinya, jenis array dibangun dengan mengikuti nama jenis dengan tanda kurung siku. Misalnya, Int32[] adalah array dimensi tunggal Int32.

Demikian pula, jenis nilai nullable juga tidak harus didefinisikan sebelum dapat digunakan. Untuk setiap jenis nilai yang tidak dapat diubah ke null T (kecuali String), ada jenis nullable yang sesuai Windows.Foundation.IReference<T>, yang dapat menyimpan nilai tambahan null. Misalnya, Windows.Foundation.IReference<Int32> adalah jenis yang dapat menampung bilangan bulat 32-bit apa pun, atau nilai null. Lihat juga IReference<T>.

Terakhir, MIDL 3.0 mendukung jenis Objek , yang memetakan ke antarmuka Windows Runtime IInspectable. Antarmuka dan runtimeclass jenis referensi yang secara konseptual berasal dari jenis Objek ; mendelegasikan tidak.

Ekspresi dalam nilai enumerasi

Dengan MIDL 3.0, Anda hanya dapat menggunakan ekspresi dalam definisi nilai konstanta bernama jenis enumerasi; dengan kata lain, dalam penginisialisasi enumerasi.

Ekspresi dibangun dari operand operator dan . Operator dalam ekspresi menunjukkan operasi mana yang akan diterapkan ke operand. Contoh operator termasuk +, -, *, /, dan new. Contoh operand termasuk literal, bidang, variabel lokal, dan ekspresi.

Saat ekspresi berisi beberapa operator, prioritas operator mengontrol urutan operator individu dievaluasi. Misalnya, ekspresi x + y * z dievaluasi sebagai x + (y * z) karena operator * memiliki prioritas yang lebih tinggi daripada operator + . Operasi logis lebih rendah diutamakan daripada operasi bitwise.

Tabel berikut ini meringkas operator MIDL 3.0, mencantumkan kategori operator dalam urutan prioritas dari tertinggi hingga terendah. Operator dalam kategori yang sama memiliki prioritas yang sama.

Golongan Ekspresi Deskripsi
Utama x++ Pasca-kenaikan
x-- Pasca-dekreasi
Unari +x Identitas
-x Negasi
!x Negasi logis
~x Negasi bitwise
++x Pra-kenaikan
--x Pra-dekreasi
Multiplikatif x * y Perkalian
x / y Divisi
x % y Sisa
Aditif x + y Penambahan, Penggalian string, kombinasi delegasi
x – y Pengurangan, penghapusan delegasi
Menggeser x << y Geser ke kiri
x >> y Geser ke kanan
Bitwise DAN x & y Integer bitwise AND
Bitwise XOR x ^ y Bilangan bulat bitwise XOR
Bitwise ATAU x | y Integer bitwise OR
LOGIS AND x && y Boolean logis AND
LOGIS ATAU x || y Logis Boolean OR

Kelas

Kelas (atau kelas runtime) adalah yang paling mendasar dari jenis MIDL 3.0. Kelas adalah definisi dari agregasi metode, properti, dan peristiwa dalam satu unit. Kelas mendukungpewarisan dan polimorfisme —mekanisme di mana kelas turunan dapat memperluas dan mengkhususkan kelas dasar .

Anda menentukan jenis kelas baru menggunakan definisi kelas. Definisi kelas dimulai dengan header yang menentukan kata kunci runtimeclass, nama kelas, kelas dasar (jika diberikan), dan antarmuka yang diimplementasikan oleh kelas . Header diikuti oleh isi kelas, yang terdiri dari daftar deklarasi anggota yang ditulis antara pemisah { dan }.

Berikut adalah definisi kelas sederhana bernama Area.

runtimeclass Area
{
    Area(Int32 width, Int32 height);

    Int32 Height;
    Int32 Width;

    static Int32 NumberOfAreas { get; };
}

Ini mendefinisikan kelas Windows Runtime baru bernama Area, yang memiliki konstruktor yang mengambil dua parameter Int32 , dua properti baca-tulis Int32 bernama Height dan Width, dan properti baca-saja statis bernama NumberOfAreas.

Secara default, runtimeclass disegel, dan turunan darinya tidak diizinkan. Lihatkelas Dasar .

Untuk mengikat XAML ke model tampilan, kelas runtime model tampilan perlu ditentukan di MIDL. Lihat kontrol XAML ; ikat ke properti C++/WinRT untuk detail selengkapnya.

Anda dapat menyatakan bahwa kelas tidak mendukung instans (dan akibatnya hanya harus berisi anggota statis) dengan mengawali definisi kelas runtime dengan kata kunci static. Menambahkan anggota non-statis ke kelas kemudian menyebabkan kesalahan kompilasi.

static runtimeclass Area
{
    static Int32 NumberOfAreas { get; };
}

Kelas statis berbeda dari kelas kosong. Lihat juga kelas Kosong.

Anda dapat menunjukkan bahwa definisi kelas tidak lengkap dengan mengawali definisi kelas runtime dengan kata kunci partial. Semua definisi kelas parsial yang ditemui oleh pengompilasi digabungkan ke dalam satu kelas runtime. Fitur ini terutama untuk skenario penulisan XAML, di mana beberapa kelas parsial dihasilkan mesin.

Pengubah Arti
Statis Kelas tidak memiliki instans. Akibatnya, hanya anggota statis yang diizinkan.
Parsial Definisi kelas tidak lengkap.

Lihat Komposisi dan aktivasi untuk pengubah tingkat lanjut.

Pengubah akses anggota

Karena MIDL 3.0 adalah bahasa definisi untuk menjelaskan permukaan publik jenis Windows Runtime, tidak perlu sintaks eksplisit untuk mendeklarasikan aksesibilitas publik anggota. Semua anggota secara implisit bersifat publik. Itulah sebabnya MIDL 3.0 tidak memerlukan kata kunci public (redundan secara efektif).

Kelas dasar

Definisi kelas dapat menentukan kelas dasar dengan mengikuti nama kelas dan parameter jenis dengan titik dua dan nama kelas dasar. Menghilangkan spesifikasi kelas dasar sama dengan berasal dari jenis Object (dengan kata lain, dari IInspectable).

Catatan

Kelas model tampilan Anda—pada kenyataannya, kelas runtime apa pun yang Anda tentukan dalam aplikasi Anda—tidak perlu berasal dari kelas dasar.

Setiap kelas runtime yang Anda tentukan dalam aplikasi yang lakukan berasal dari kelas dasar dikenal sebagai kelas yang dapat disusun . Dan ada kendala di sekitar kelas yang dapat dikomposisikan. Agar aplikasi lulus Kit Sertifikasi Aplikasi Windows pengujian yang digunakan oleh Visual Studio dan oleh Microsoft Store untuk memvalidasi pengiriman (dan oleh karena itu agar aplikasi berhasil diserap ke dalam Microsoft Store), kelas yang dapat disusun pada akhirnya harus berasal dari kelas dasar Windows. Artinya kelas di akar hierarki warisan harus merupakan jenis yang berasal dari namespace Windows.*.

Lihat kontrol XAML ; ikat ke properti C++/WinRT untuk detail selengkapnya.

Dalam contoh berikutnya, kelas dasar Volume adalahArea , dan kelas dasar Area Windows.UI.Xaml.DependencyObject .

unsealed runtimeclass Area : Windows.UI.Xaml.DependencyObject
{
    Area(Int32 width, Int32 height);
    Int32 Height;
    Int32 Width;
}

runtimeclass Volume : Area
{
    Volume(Int32 width, Int32 height, Int32 depth);
    Int32 Depth;
}

Catatan

Di sini, Area dan Volume didefinisikan dalam file sumber yang sama. Untuk diskusi tentang pro dan kontra, lihat kelas runtime Factoring ke dalam file Midl (.idl).

Kelas mewarisi anggota kelas dasarnya. Pewarisan berarti bahwa kelas secara implisit berisi semua anggota kelas dasarnya, kecuali untuk konstruktor kelas dasar. Kelas turunan dapat menambahkan anggota baru ke anggota yang diwariskannya, tetapi tidak dapat menghapus definisi anggota yang diwariskan.

Dalam contoh sebelumnya, Volume mewarisi properti Tinggi dan Lebar dariArea . Jadi, setiap instans Volume berisi tiga properti:Tinggi , Lebar, danKedalaman .

Secara umum, aturan resolusi jenis mengharuskan nama jenis sepenuhnya memenuhi syarat saat dirujuk. Pengecualian adalah ketika jenis telah ditentukan dalam namespace yang sama dengan jenis saat ini. Contoh di atas berfungsi seperti yang ditulis jika Area dan Volume keduanya berada di namespace yang sama.

Antarmuka yang diimplementasikan

Definisi kelas juga dapat menentukan daftar antarmuka yang diterapkan kelas. Anda menentukan antarmuka sebagai daftar antarmuka yang dipisahkan koma mengikuti kelas dasar (opsional).

Dalam contoh di bawah ini, kelas Area mengimplementasikan antarmuka IStringable; dan kelas Volume mengimplementasikan IStringable dan antarmuka IEquatable hipotetis.

unsealed runtimeclass Area : Windows.Foundation.IStringable
{
    Area(Int32 width, Int32 height);
    Int32 Height;
    Int32 Width;
}

runtimeclass Volume : Area, Windows.Foundation.IStringable, IEquatable
{
    Volume(Int32 width, Int32 height, Int32 depth);
    Int32 Depth;
}

Di MIDL, Anda tidak mendeklarasikan anggota antarmuka di kelas . Anda, tentu saja, harus mendeklarasikan dan mendefinisikannya pada implementasi aktual.

Anggota

Anggota kelas adalah anggota statis atau anggota instans . Anggota statis termasuk dalam kelas. Anggota instans milik objek (yaitu, instans kelas).

Tabel ini memperlihatkan jenis anggota yang dapat dimuat oleh kelas.

Jenis anggota Deskripsi
Konstruktor Tindakan yang diperlukan untuk menginisialisasi instans kelas, atau untuk menginisialisasi kelas itu sendiri
Properti Tindakan yang terkait dengan membaca dan menulis properti bernama dari instans kelas, atau kelas itu sendiri
Metode Komputasi dan tindakan yang dapat dilakukan oleh instans kelas, atau oleh kelas itu sendiri
Peristiwa Pemberitahuan yang dapat dinaikkan oleh instans kelas

Konstruktor

MIDL 3.0 mendukung deklarasi konstruktor instans. Konstruktor instans adalah metode yang mengimplementasikan tindakan yang diperlukan untuk menginisialisasi instans kelas. Konstruktor mungkin tidak statis.

Konstruktor dinyatakan seperti metode instans (tetapi tanpa jenis pengembalian), dan dengan nama yang sama dengan kelas yang berisi.

Konstruktor instans dapat kelebihan beban. Misalnya, kelas Test di bawah ini mendeklarasikan tiga konstruktor instans; satu tanpa parameter (konstruktor default ), yang mengambil parameter Int32, dan yang mengambil dua parameter Ganda (konstruktor berparameter).

runtimeclass Test
{
    Test();
    Test(Int32 x);
    Test(Double x, Double y);
}

Untuk detail tentang sintaks untuk daftar parameter, lihat metode di bawah ini.

Properti instans, metode, dan peristiwa diwariskan. Konstruktor instans tidak diwariskan (dengan satu pengecualian), dan kelas tidak memiliki konstruktor instans selain yang benar-benar dideklarasikan di kelas. Jika tidak ada konstruktor instans yang disediakan untuk kelas, maka Anda tidak dapat langsung membuat instans kelas. Untuk kelas seperti itu, Anda biasanya memiliki metode pabrik di tempat lain yang mengembalikan instans kelas.

Pengecualian adalah kelas yang tidak disegel. Kelas yang tidak tersegel dapat memiliki satu atau beberapa konstruktor yang dilindungi.

Properti

Properti secara konseptual mirip dengan bidang (misalnya, bidang C#; atau bidang struktur MIDL 3.0). Properti dan bidang adalah anggota dengan nama dan jenis terkait. Namun, tidak seperti bidang, properti tidak menunjukkan lokasi penyimpanan. Sebagai gantinya, properti memiliki aksesor yang menentukan fungsi yang akan dijalankan saat Anda membaca atau menulis properti.

Properti dinyatakan seperti bidang struct, kecuali bahwa deklarasi berakhir dengan kata kunci get dan/atau kata kunci set yang ditulis antara pemisah { dan }, dan berakhiran titik koma.

Properti yang memiliki kata kunci get dan kata kunci set adalah properti baca-tulis . Properti yang hanya memiliki kata kunci get adalah properti baca-saja . Windows Runtime tidak mendukung properti tulis-saja.

Misalnya, kelas Area, yang terlihat sebelumnya, berisi dua properti baca-tulis bernama Tinggi danLebar .

unsealed runtimeclass Area
{
    Int32 Height { get; set; };
    Int32 Width; // get and set are implied if both are omitted.
}

Deklarasi Lebar menghilangkan kurung kurawal dan kata kunci get dan set. Kelalaian menyiratkan bahwa properti adalah baca-tulis, dan secara semantik identik dengan menyediakan kata kunci get dan set dalam urutan tersebut —get, diikuti oleh set.

Selain itu, Anda hanya dapat menentukan kata kunci get untuk menunjukkan bahwa properti bersifat baca-saja.

// Read-only instance property returning mutable collection.
Windows.Foundation.Collections.IVector<Windows.UI.Color> Colors { get; };

Windows Runtime tidak mendukung properti tulis-saja. Tetapi Anda hanya dapat menentukan kata kunci set untuk merevisi properti baca-saja yang ada menjadi properti baca-tulis. Ambil versi Area ini sebagai contoh.

unsealed runtimeclass Area
{
    ...
    Color SurfaceColor { get; };
}

Jika Anda kemudian ingin membuat properti SurfaceColor baca-tulis, dan Anda tidak perlu mempertahankan kompatibilitas biner dengan definisi sebelumnya dari Area (misalnya, kelas Area adalah jenis dalam aplikasi yang Anda kompilasi ulang setiap kali), maka Anda cukup menambahkan kata kunci ke deklarasi SurfaceColor yang ada seperti ini.

unsealed runtimeclass Area
{
    ...
    Color SurfaceColor { get; set; };
}

Jika, di sisi lain, Anda memerlukan stabilitas biner (misalnya, kelas Area adalah komponen dalam pustaka yang Anda kirimkan ke pelanggan), maka Anda tidak dapat menambahkan kata kunci ke deklarasi properti yang ada. Melakukannya mengubah antarmuka biner ke kelas Anda.

Dalam hal ini, tambahkan properti set kata kunci ke definisi tambahan properti di akhir kelas seperti ini.

unsealed runtimeclass Area
{
    ...
    Color SurfaceColor { get; };
    ...
    Color SurfaceColor { set; };
}

Pengkompilasi menghasilkan kesalahan untuk properti tulis-saja. Tapi bukan itu yang sedang dilakukan di sini. Karena deklarasi properti sebelumnya sebagai baca-saja, penambahan kata kunci yang ditetapkan tidak mendeklarasikan properti tulis-saja, melainkan properti baca-tulis.

Implementasi Windows Runtime properti adalah satu atau dua metode aksesor pada antarmuka. Urutan dapatkan dan atur kata kunci dalam deklarasi properti menentukan urutan metode dapatkan dan atur aksesor di antarmuka backing.

Aksesor get sesuai dengan metode tanpa parameter dengan nilai yang dikembalikan dari jenis properti —getter properti.

Aksesor set sesuai dengan metode dengan parameter tunggal bernama nilai , dan tanpa jenis pengembalian—setter properti.

Akibatnya, kedua deklarasi ini menghasilkan antarmuka biner yang berbeda.

Color SurfaceColor { get; set; };
Color SurfaceColor { set; get; };
Properti statis dan instans

Mirip dengan metode, MIDL 3.0 mendukung properti instans dan properti statis. Properti statis dinyatakan dengan awalan pengubah static, dan properti instans dideklarasikan tanpanya.

Metode

Metode adalah anggota yang mengimplementasikan komputasi atau tindakan yang dapat dilakukan oleh instans kelas, atau oleh kelas itu sendiri. Metode statis diakses melalui kelas . Metode instans diakses melalui instans kelas.

Metode memiliki daftar parameter (mungkin kosong), yang mewakili nilai atau referensi variabel yang diteruskan ke metode . Metode juga memiliki jenis pengembalian , yang menentukan jenis nilai yang dihitung dan dikembalikan oleh metode . Jenis pengembalian metode void jika tidak mengembalikan nilai.

// Instance method with no return value.
void AddData(String data);

// Instance method *with* a return value.
Int32 GetDataSize();

// Instance method accepting/returning a runtime class.
// Notice that you don't say "&" nor "*" for reference types.
BasicClass MergeWith(BasicClass other);

// Asynchronous instance methods.
Windows.Foundation.IAsyncAction UpdateAsync();
Windows.Foundation.IAsyncOperation<Boolean> TrySaveAsync();

// Instance method that returns a value through a parameter.
Boolean TryParseInt16(String input, out Int16 value);

// Instance method that receives a reference to a value type.
Double CalculateArea(ref const Windows.Foundation.Rect value);

// Instance method accepting or returning a conformant array.
void SetBytes(UInt8[] bytes);
UInt8[] GetBytes();

// instance method that writes to a caller-provided conformant array
void ReadBytes(ref UInt8[] bytes);

tanda tangan metode harus unik di kelas tempat metode dideklarasikan. Tanda tangan metode terdiri dari nama metode, jenis parameternya, dan/atau jumlah parameternya. Tanda tangan metode tidak menyertakan jenis pengembalian.

Pengubah visibilitas metode

Metode mungkin memiliki salah satu dari dua pengubah visibilitas opsional ketika metode ada di kelas turunan.

Pengubah yang dapat diganti menyatakan bahwa metode ini dapat ditimpa oleh metode (dengan nama dan tanda tangan yang sama) milik subkelas.

Pengubah yang dilindungi menyatakan bahwa metode ini hanya dapat diakses oleh anggota di kelas turunan berikutnya.

Kelebihan muatan metode

Metode kelebihan beban memungkinkan beberapa metode di kelas yang sama memiliki nama yang sama selama parameternya berbeda dalam jumlah (dengan kata lain metode memiliki aritas yang berbeda).

runtimeclass Test
{
    static void F();
    static void F(Double x);
    static void F(Double x, Double y);
}

Catatan

Semua metode dengan nama yang sama harus memiliki aritas yang berbeda. Itu karena bahasa pemrograman yang ditik lemah tidak mendukung kelebihan beban berdasarkan jenis.

Parameter

Parameter digunakan untuk meneruskan nilai atau referensi variabel ke metode . Parameter menjelaskan slot dengan jenis dan nama, dan secara opsional beberapa kata kunci pengubah. Argumen adalah nilai aktual yang diteruskan di slot tersebut dari pemanggil metode ke penerima panggilan.

Parameter metode mendapatkan nilainya dari argumen tertentu yang ditentukan saat metode dipanggil. Cara argumen diteruskan antara penelepon dan penerima panggilan tergantung pada jenis parameter. Secara default, semua parameter parameter input, yaitu parameter tersebut di-marshal dari pemanggil ke penerima panggilan saja. Kata kunci pengubah ref, ref const, dan out dapat ditambahkan untuk memodifikasi arah default marshaling antara penelepon dan penerima panggilan, dan membuat parameter output . Namun, tidak semua kata kunci valid dengan semua jenis parameter; kombinasi yang valid dirinci di bawah ini.

Penting

Common Language Runtime (CLR) memiliki konsep dan kata kunci pengubah yang mungkin tampak mirip dengan yang dijelaskan di bagian ini. Namun dalam praktiknya, itu tidak terkait, dan efek pengubah ini khusus untuk desain dan fungsi Windows Runtime.

Jenis nilai secara implisit parameter input, dan secara default salinan argumen diteruskan dari pemanggil ke penerima panggilan. Parameter nilai dapat diubah menjadi parameter output dengan kata kunci out; dalam hal ini argumen dinamai sebagai gantinya dari penerima panggilan kembali ke penelepon saja.

runtimeclass Test
{
    static void Divide(Int32 x, Int32 y, out Int32 result, out Int32 remainder);
}

Sebagai pengoptimalan performa khusus, jenis struct (dan tidak ada jenis lain), yang biasanya diteruskan oleh nilai sebagai salinan lengkap, dapat dibuat untuk diteruskan oleh pointer ke struct yang tidak dapat diubah. Ini dicapai dengan kata kunci ref const (tidakconst ref), yang menandai parameter struct sebagai parameter input, tetapi menginstruksikan marshaler untuk meneruskan penunjuk ke penyimpanan struct, alih-alih meneruskan salinan lengkap struct. Perhatikan bagaimanapun bahwa struktur tidak dapat diubah; pointer secara konseptual const pointer. Tidak ada tinju yang terlibat. Ini adalah pilihan praktis ketika menerima nilai sebesar Matrix4x4, misalnya.

runtimeclass Test
{
    static Boolean IsIdentity(ref const Windows.Foundation.Numerics.Matrix4x4 m);
}

Jenis referensi juga secara implisit input parameter, yang berarti bahwa penelepon bertanggung jawab untuk mengalokasikan objek dan meneruskan referensi ke dalamnya sebagai argumen; namun karena argumen adalah referensi ke objek, modifikasi pada objek tersebut oleh penerima panggilan diamati oleh pemanggil setelah panggilan. Atau, jenis referensi dapat dibuat parameter output dengan kata kunci out. Dalam hal ini peran dibalik; callee adalah orang yang mengalokasikan objek dan mengembalikannya kembali ke pemanggil. Sekali lagi, kata kunci ref tidak dapat digunakan secara umum dengan jenis referensi (lihat pengecualian di bawah).

runtimeclass Test
{
    static void CreateObjectWithConfig(Config config, out MyClass newObject);
}

Tabel berikut ini meringkas perilaku kata kunci marshaling untuk parameter nilai dan parameter referensi:

Perilaku Dialokasikan oleh Kata kunci Jenis Komentar
Parameter input Pemanggil (tidak ada) Semua jenis Perilaku default
ref const Struct saja Pengoptimalan performa
Parameter output Penerima Panggilan out Semua jenis

Windows Runtime mendukung jenis array, yang perilakunya sebagai parameter agak berbeda. Array adalah struktur data yang berisi sejumlah variabel yang disimpan secara berurutan dan diakses melalui indeks. Variabel yang terkandung dalam array—juga disebut elemen array—adalah semua jenis yang sama, dan jenis ini disebut jenis elemen array.

MIDL 3.0 mendukung deklarasi array dimensi tunggal .

Parameter array adalah jenis referensi, dan seperti semua jenis referensi secara default adalah parameter input. Dalam hal ini, penelepon mengalokasikan array ke penerima panggilan, yang dapat membaca elemennya tetapi tidak dapat mengubahnya (baca-saja). Ini disebut pola array pass . Atau, pola array isian dapat digunakan dengan menambahkan kata kunci ke parameter; dalam pengaturan itu, array masih dialokasikan oleh pemanggil, tetapi secara konseptual merupakan parameter output dalam arti bahwa penerima panggilan akan mengisi nilai elemen array. Terakhir, pola terakhir adalah menerima array di mana (seperti semua parameter referensi output) penerima panggilan mengalokasikan dan menginisialisasi argumen sebelum dikembalikan ke pemanggil.

runtimeclass Test
{
    // Pass array pattern: read-only array from caller to callee
    void PassArray(Int32[] values);

    // Fill array pattern: caller allocates array for callee to fill
    void FillArray(ref Int32[] values);

    // Receive array pattern: callee allocates and fill an array returned to caller
    void ReceiveArray(out Int32[] values);
}

Tabel berikut ini meringkas perilaku untuk array dan elemennya:

Pola array Kata kunci Dialokasikan oleh Akses elemen oleh penerima panggilan
"Pass array" (tidak ada) Pemanggil Baca-saja
"Isi array" ref Pemanggil Tulis-saja
"Terima array" out Penerima Panggilan Baca-tulis

Untuk informasi selengkapnya tentang menggunakan parameter array gaya C—juga dikenal sebagai array yang sesuai—dengan C++/WinRT, lihat parameter Array .

Metode statis dan instans

Metode yang dideklarasikan dengan awalan pengubah static adalah metode statis . Metode statis tidak memiliki akses ke instans tertentu, dan oleh karena itu hanya dapat langsung mengakses anggota statis kelas lainnya.

Metode yang dideklarasikan tanpa pengubah static adalah metode instans . Metode instans memiliki akses ke instans tertentu, dan dapat mengakses anggota statis dan instans kelas.

Kelas Entitas berikut memiliki anggota statis dan instans.

runtimeclass Entity
{
    Int32 SerialNo { get; };
    static Int32 GetNextSerialNo();
    static void SetNextSerialNo(Int32 value);
}

Setiap instans Entitas berisi nomor serinya sendiri (dan mungkin beberapa informasi lain yang tidak ditampilkan di sini). Secara internal, konstruktor Entitas (yang seperti metode instans) menginisialisasi instans baru dengan nomor seri berikutnya yang tersedia.

Properti SerialNo menyediakan akses ke nomor seri untuk instans tempat Anda memanggil properti mendapatkan metode.

Metode statis GetNextSerialNo dan SetNextSerialNo dapat mengakses nomor seri internal berikutnya yang tersedia anggota statis dari kelas Entitas .

Metode yang dapat diambil alih dan dilindungi

Semua metode dalam jenis Windows Runtime secara efektif virtual. Ketika metode virtual dipanggil, jenis run-time instans tempat pemanggilan tersebut dilakukan menentukan implementasi metode aktual yang akan dipanggil.

Metode dapat ditimpa di kelas turunan. Ketika deklarasi metode instans menyertakan pengubah overridable, metode dapat diambil alih oleh kelas turunan. Apakah kelas turunan benar-benar mengambil alih metode kelas dasar yang dapat diganti ditentukan oleh implementasi; itu tidak ada dalam metadata. Jika kelas turunan mendeklarasikan ulang metode di kelas dasar, maka ia mendeklarasikan metode baru yang duduk bersama metode kelas turunan, daripada menimpanya.

Ketika deklarasi metode instans menyertakan pengubah protected, metode hanya terlihat oleh kelas turunan.

Peristiwa

Deklarasi peristiwa adalah anggota yang menentukan bahwa kelas adalah sumber peristiwa. Sumber peristiwa semacam itu memberikan pemberitahuan kepada penerima mana pun yang mengimplementasikan delegasi (metode dengan tanda tangan tertentu).

Anda mendeklarasikan peristiwa menggunakan kata kunci event, diikuti dengan nama jenis delegasi (yang menjelaskan tanda tangan metode yang diperlukan), diikuti dengan nama peristiwa. Berikut adalah contoh peristiwa yang menggunakan jenis delegasi yang ada dari platform.

runtimeclass Area
{
    ...
    event Windows.UI.Xaml.WindowSizeChangedEventHandler SizeChanged;
    ...
}

Deklarasi peristiwa secara implisit menambahkan dua metode ke kelas: menambahkan metode, yang dipanggil klien untuk menambahkan penanganan aktivitas ke sumber, dan menghapus metode, yang dipanggil klien untuk menghapus penanganan aktivitas yang ditambahkan sebelumnya. Berikut adalah contoh lainnya.

// Instance event with no meaningful payload.
event Windows.Foundation.TypedEventHandler<BasicClass, Object> Changed;

// Instance event with event parameters.
event Windows.Foundation.TypedEventHandler<BasicClass, BasicClassSaveCompletedEventArgs> SaveCompleted;

// Static event with no meaningful payload.
static event Windows.Foundation.EventHandler<Object> ResetOccurred;

// Static event with event parameters.
static event Windows.Foundation.EventHandler<BasicClassDeviceAddedEventArgs> DeviceAdded;

Menurut konvensi, dua parameter selalu diteruskan ke penanganan aktivitas Windows Runtime: identitas pengirim, dan objek argumen peristiwa. Pengirim adalah objek yang menaikkan peristiwa, atau null untuk peristiwa statis. Jika peristiwa tidak memiliki payload yang bermakna, maka argumen peristiwa adalah objek yang nilainya null.

Delegasi

Jenis delegasi menentukan metode dengan daftar parameter tertentu dan jenis pengembalian. Satu instans peristiwa dapat berisi sejumlah referensi ke instans jenis delegasinya. Deklarasi ini mirip dengan metode anggota reguler, kecuali ada di luar kelas runtime, dan diawali dengan kata kunci delegate.

Delegasi memungkinkan untuk memperlakukan metode sebagai entitas yang dapat ditetapkan ke variabel dan diteruskan sebagai parameter. Delegasi mirip dengan konsep penunjuk fungsi yang ditemukan dalam beberapa bahasa lain. Tetapi, tidak seperti penunjuk fungsi, delegasi berorientasi objek dan aman jenis.

Jika kita tidak ingin menggunakan jenis delegasi WindowSizeChangedEventHandler dari platform, maka kita dapat menentukan jenis delegasi kita sendiri.

delegate void SizeChangedHandler(Object sender, Windows.UI.Core.WindowSizeChangedEventArgs args);

Instans jenis delegasi SizeChangedHandler kami dapat mereferensikan metode apa pun yang mengambil dua argumen (Objek , dan WindowSizeChangedEventArgs), dan mengembalikan kekosongan. Setelah kita membahas struktur, Anda juga akan dapat mengganti parameter WindowSizeChangedEventArgs dengan arg peristiwa jenis Anda sendiri.

Properti delegasi yang menarik dan berguna adalah tidak tahu atau peduli dengan kelas metode yang direferensikannya; yang penting adalah bahwa metode yang direferensikan memiliki parameter yang sama dan jenis pengembalian sebagai delegasi.

Anda dapat secara opsional mengaitkan deklarasi delegasi dengan [uuid(...)].

Lihat juga Delegasi yang mengembalikanHRESULT .

Struktur

Struct adalah struktur data yang dapat berisi anggota data (bidang). Tapi, tidak seperti kelas, struct adalah jenis nilai.

Struktur sangat berguna untuk struktur data kecil yang memiliki semantik nilai. Bilangan kompleks, atau titik dalam sistem koordinat, adalah contoh struktur yang baik. Penggunaan struktur daripada kelas untuk struktur data kecil dapat membuat perbedaan besar dalam jumlah alokasi memori yang dilakukan aplikasi.

Mari kita gunakan contoh untuk membedakan kelas dan struktur. Berikut adalah versi Point pertama sebagai kelas .

runtimeclass Point
{
    Point(Int32 x, Int32 y);
    Int32 x;
    Int32 y;
}

Program C# ini membuat dan menginisialisasi array 100 instans Point. Dengan Point diimplementasikan sebagai kelas, 101 objek terpisah dibuat: satu untuk objek array itu sendiri; dan satu untuk masing-masing dari 100 elemen Titik .

class Test
{
    static Test()
    {
        Point[] points = new Point[100];
        for (Int32 i = 0; i < 100; ++i) points[i] = new Point(i, i);
    }
}

Alternatif yang lebih berkinerja adalah membuat Point struct, bukan kelas.

struct Point
{
    Int32 x;
    Int32 y;
};

Sekarang, hanya satu objek yang dibuat—objek array itu sendiri. Elemen Point disimpan sejajar di dalam array; pengaturan memori yang dapat digunakan cache prosesor untuk efek yang kuat.

Mengubah struktur adalah perubahan pemecahan biner. Oleh karena itu, struktur yang diimplementasikan sebagai bagian dari Windows itu sendiri tidak diubah setelah diperkenalkan.

Antarmuka

Antarmuka menentukan kontrak yang dapat diimplementasikan oleh kelas. Antarmuka dapat berisi metode, properti, dan peristiwa—sama seperti kelas.

Tidak seperti kelas, antarmuka tidak menyediakan implementasi anggota yang ditentukannya. Ini hanya menentukan anggota yang harus disediakan oleh kelas apa pun yang mengimplementasikan antarmuka.

Antarmuka mungkin memerlukan kelas yang mengimplementasikan antarmuka untuk juga mengimplementasikan antarmuka lain. Dalam contoh berikut, antarmuka IComboBox mengharuskan kelas apa pun yang menerapkan IComboBox, juga menerapkan ITextBox dan IListBox. Selain itu, kelas yang menerapkan IComboBox juga harus menerapkan IControl. Itu karena ITextBox dan IListBox memerlukan .

interface IControl
{
    void Paint();
}

interface ITextBox requires IControl
{
    void SetText(String text);
}

interface IListBox requires IControl
{
    void SetItems(String[] items);
}

interface IComboBox requires ITextBox, IListBox
{
    ...
}

Kelas dapat menerapkan nol atau lebih antarmuka. Dalam contoh berikutnya, EditBox kelas mengimplementasikan IControl dan IDataBound.

interface IDataBound
{
    void Bind(Binder b);
}

runtimeclass EditBox : IControl, IDataBound
{
}

Untuk jenis Windows Runtime di platform Windows, antarmuka didefinisikan jika pengembang yang mengonsumsi jenis tersebut diharapkan untuk mengimplementasikan antarmuka. Kasus penggunaan lain untuk menentukan antarmuka adalah ketika beberapa kelas runtime mengimplementasikan antarmuka, dan pengembang yang menggunakan kelas runtime tersebut akan mengakses berbagai jenis objek secara generis (dan dengan demikian secara polimorfik) melalui antarmuka umum tersebut.

Catatan

Pikirkan dua kali tentang menggunakan kata kunci requires di MIDL 3.0. Ini dapat menyebabkan desain yang berantakan, terutama ketika penerapan versi diperhitungkan.

Enum

Jenis enum (atau jenis enumerasi, atau enumerasi) adalah jenis nilai yang berbeda dengan sekumpulan konstanta bernama. Contoh berikut menentukan dan menggunakan jenis enum bernama Color dengan tiga nilai konstanta: Red, Green, dan Blue.

enum Color
{
    Red,
    Green,
    Blue, // Trailing comma is optional, but recommended to make future changes easier.
};

Setiap jenis enum memiliki jenis integral yang sesuai yang disebut jenis mendasar dari jenis enum. Jenis enum yang mendasar adalah int32 atau UInt32.

Windows Runtime mendukung dua jenis enum: enum normal, dan bendera enum. Enum dari jenis normal mengekspresikan sekumpulan nilai eksklusif; sementara salah satu jenis bendera mewakili sekumpulan nilai Boolean. Untuk mengaktifkan operator bitwise untuk enum bendera, pengkompilasi MIDL 3.0 menghasilkan kelebihan beban operator C++.

Enum bendera memiliki atribut [flags] diterapkan. Dalam hal ini, jenis enum yang mendasar adalah UInt32. Ketika atribut [flags] tidak ada (enum normal), jenis enum yang mendasar adalah Int32. Tidak mungkin untuk mendeklarasikan enum sebagai jenis lainnya.

[flags]
enum SetOfBooleanValues
{
    None   = 0x00000000,
    Value1 = 0x00000001,
    Value2 = 0x00000002,
    Value3 = 0x00000004,
};

Format penyimpanan jenis enum dan rentang nilai yang mungkin ditentukan oleh jenis yang mendasarnya. Kumpulan nilai yang dapat diambil oleh jenis enum tidak dibatasi oleh anggota enum yang dideklarasikan.

Contoh berikut mendefinisikan jenis enum bernama Alignment, dengan jenis Int32.

enum Alignment
{
    Left = -1,
    Center = 0,
    Right = 1
};

Seperti juga berlaku untuk C dan C++, enum MIDL 3.0 dapat menyertakan ekspresi konstanta yang menentukan nilai anggota (seperti yang terlihat di atas). Nilai konstanta untuk setiap anggota enum harus berada dalam rentang jenis enum yang mendasar. Ketika deklarasi anggota enum tidak secara eksplisit menentukan nilai, anggota diberi nilai nol (jika itu adalah anggota pertama dalam jenis enum), atau nilai anggota enum sebelumnya secara tekstual ditambah satu.

Contoh berikut mendefinisikan jenis enum bernama Izin, dengan jenis UInt32yang mendasar.

[flags]
enum Permissions
{
    None = 0x0000,
    Camera = 0x0001,
    Microphone = 0x0002
};

Atribut

Jenis, anggota, dan entitas lain dalam kode sumber MIDL 3.0 mendukung pengubah yang mengontrol aspek tertentu dari perilaku mereka. Misalnya, aksesibilitas metode dikontrol menggunakan pengubah akses protected. MIDL 3.0 menggeneralisasi kemampuan ini sehingga jenis informasi deklaratif yang ditentukan pengguna dapat dilampirkan ke entitas program, dan diambil pada run-time dari metadata.

Program menentukan informasi deklaratif tambahan ini dengan mendefinisikan dan menggunakan atribut .

Contoh berikutnya mendefinisikan atribut HelpAttribute , yang dapat ditempatkan pada entitas program untuk menyediakan tautan ke dokumentasi terkait. Seperti yang Anda lihat, atribut pada dasarnya adalah jenis struct, sehingga tidak memiliki konstruktor, dan hanya berisi anggota data.

[attributeusage(target_runtimeclass, target_event, target_method, target_property)]
attribute HelpAttribute
{
    String ClassUri;
    String MemberTopic;
}

Atribut dapat diterapkan dengan memberikan namanya, bersama dengan argumen apa pun, di dalam kurung siku tepat sebelum deklarasi terkait. Jika nama atribut berakhiran Atribut, maka bagian nama tersebut dapat dihilangkan saat atribut dirujuk. Misalnya, atribut HelpAttribute dapat digunakan seperti ini.

[Help("https://docs.contoso.com/.../BookSku", "BookSku class")]
runtimeclass BookSku : Windows.UI.Xaml.Data.INotifyPropertyChanged
{
    [Help("https://docs.contoso.com/.../BookSku_Title", "Title method")]
    String Title;
}

Anda dapat menerapkan atribut yang sama ke beberapa deklarasi dengan menggunakan blok cakupan mengikuti atribut . Artinya, atribut segera diikuti oleh kurung kurawal di sekitar deklarasi tempat atribut berlaku.

runtimeclass Widget
{
    [Help("https://docs.contoso.com/.../Widget", "Widget members")]
    {
        void Display(String text);
        void Print();
        Single Rate;
    }
}

Atribut yang diimplementasikan sebagai bagian dari Windows itu sendiri biasanya berada di namespace Windows.Foundation .

Seperti yang ditunjukkan pada contoh pertama, Anda menggunakan atribut [attributeusage(<target>)] pada definisi atribut Anda. Nilai target yang valid adalah target_all, target_delegate, target_enum, target_event, target_field, target_interface, target_method, target_parameter, target_property, target_runtimeclass, dan target_struct. Anda dapat menyertakan beberapa target dalam tanda kurung, dipisahkan oleh koma.

Atribut lain yang dapat Anda terapkan ke atribut adalah [allowmultiple] dan [attributename("<name>")].

Jenis berparameter

Contoh di bawah ini menghasilkan kesalahan MIDL2025: [msg]sintaks error [context]: mengharapkan > atau, dekat ">>".

Windows.Foundation.IAsyncOperation<Windows.Foundation.Collections.IVector<String>> RetrieveCollectionAsync();

Sebagai gantinya, sisipkan spasi antara dua karakter > sehingga sepasang karakter penutup templat tidak disalahartikan sebagai operator shift kanan.

Windows.Foundation.IAsyncOperation<Windows.Foundation.Collections.IVector<String> > RetrieveCollectionAsync();

Contoh di bawah ini menghasilkan kesalahan MIDL2025: [msg]sintaks error [context]: mengharapkan > atau, dekat "[". Ini karena tidak valid untuk menggunakan array sebagai argumen jenis parameter ke antarmuka berparameter.

Windows.Foundation.IAsyncOperation<Int32[]> RetrieveArrayAsync();

Untuk solusinya, lihat Mengembalikan array secara asinkron.