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) (.idl file). 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 untuk menghias 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 secara khusus dan hanya dirancang untuk menentukan jenis. Anda akan menggunakan bahasa pemrograman yang berbeda untuk mengimplementasikan 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 /winrt sakelar).

Catatan

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

MIDL 1.0, 2.0, dan 3.0

Interface Definition Language (IDL) dimulai dengan sistem Distributed Computing Environment/Remote Procedure Calls (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 %WindowsSdkDir%Include<WindowsTargetPlatformVersion>\winrt Windows SDK, Maka Anda akan melihat contoh .idl file yang ditulis dengan sintaks MIDL 2.0. Ini adalah API Windows Runtime bawaan, yang dideklarasikan dalam bentuk antarmuka biner aplikasi (ABI) mereka. File-file ini ada terutama untuk digunakan alat—Anda tidak akan menulis atau menggunakan API ini dalam bentuk ini (kecuali Jika Anda menulis kode tingkat yang sangat rendah).

Lihat juga Transisi ke MIDL 3.0 dari MIDLRT klasik.

MIDL 3.0 adalah sintaks 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 WINDOWS Runtime API 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 windows Runtime API tertentu ke aplikasi C++. Teknik ini dapat dilihat dalam skenario interoperaksi—misalnya, saat beroperasi 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 memulainya, sehingga tidak akan dapat menggunakan metode tersebut karena alasan tersebut. 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++, maka 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 jenis Windows Runtime saja. Anda kemudian dapat menggunakan WRC tersebut dari aplikasi yang ditulis dalam proyeksi bahasa Windows Runtime apa pun .

Struktur definisi, dan midl.exe panggilan dari baris perintah

Konsep organisasi utama dalam definisi MIDL 3.0 adalah namespace, jenis, dan anggota. File sumber MIDL 3.0 ( .idl file) 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 .winmd file).

// 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 menentukan 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 (Harga), beberapa properti baca-saja (AuthorName melalui Judul), dan dua metode, bernama Equals dan ApplyDiscount. Perhatikan penggunaan jenis Tunggal daripada float. Dan String itu 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 ini midl.exe mengkompilasi contoh dan menghasilkan file metadata bernama Bookstore.winmd (secara default, nama .idl file digunakan).

Tip

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

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

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

where midl

Jika Anda ingin menggunakan jenis yang ditentukan dalam satu .idl file dari file yang berbeda .idl , maka Anda menggunakan direktif import . Untuk detail selengkapnya, dan contoh kode, lihat kontrol XAML; mengikat 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

Namaspace

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 dari 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 sah 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 bagi 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 mungkin 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 selanjutnya dibagi 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.

Kategori Deskripsi
Jenis nilai Jenis sederhana Integral yang ditandatangani: Int16, Int32, Int64
Integral yang tidak ditandatangani: UInt8, UInt16, UInt32, UInt64
Karakter Unicode: Karakter (mewakili UTF-16LE; unit kode Unicode 16-bit)
Untai (karakter) Unicode: String
Titik mengambang IEEE: Tunggal, Ganda
Boolean: Boolean
UUID 128 bit: Guid
Tipe enum Jenis formulir enum yang ditentukan pengguna 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: Objek
Jenis yang ditentukan pengguna dari runtimeclass formulir C {...}
Jenis antarmuka Tipe antarmuka formulir yang ditentukan pengguna I {...}
Jenis delegasi 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, Tunggal dan Ganda, mewakili data menggunakan format presisi tunggal 32-bit dan presisi Ganda 64-bit IEEE 754.

Jenis Boolean MIDL 3.0 mewakili nilai boolean; baik true atau false.

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.

Kategori 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
Floating-point 32 Tunggal 1,5 × 10−45 hingga 3,4 × 1038, presisi 7 digit
64 Double 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,
  • delegasikan jenis, dan
  • jenis enum.

Jenis atribut menentukan atribut Windows Runtime yang dapat diterapkan ke definisi jenis lain. Atribut menyediakan metadata tentang jenis di mana atribut diterapkan.

Jenis struct menentukan struktur Windows Runtime yang berisi anggota data (bidang). Struktur adalah jenis nilai, dan tidak memerlukan alokasi tumpukan. 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 secara langsung berasal dari antarmuka Windows Runtime IInspectable .

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

Jenis delegasi 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 yang mendasar implisit; baik Int32 atau UInt32. Kumpulan nilai jenis enum sama dengan kumpulan nilai dari jenis yang mendasar.

MIDL 3.0 mendukung tiga kategori jenis tambahan.

  • jenis array dimensi tunggal,
  • jenis nilai yang dapat diubah ke null, dan
  • jenis Objek .

Anda tidak perlu mendeklarasikan array dimensi tunggal sebelum Anda dapat menggunakannya. Sebaliknya, 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 nulltambahan . Misalnya, Windows.Foundation.IReference<Int32> adalah jenis yang dapat menampung bilangan bulat 32-bit, atau nilai null. Lihat juga IReference<T>.

Akhirnya, MIDL 3.0 mendukung jenis Objek , yang memetakan ke antarmuka Windows Runtime IInspectable . Jenis referensi antarmuka dan runtimeclass secara konseptual berasal dari jenis Objek ; delegasi 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 operan dan operator. Operator dalam ekspresi menunjukkan operasi mana yang akan diterapkan ke operand. Contoh operator termasuk +, -, *, /, dan new. Contoh operand termasuk harfiah, 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 logika lebih 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.

Kategori Ekspresi Deskripsi
Primer x++ Pasca-kenaikan
x-- Pasca-dekreasi
Unary +x Identitas
-x Negasi
!x Negasi logis
~x Negasi bitwise
++x Pra-kenaikan
--x Pra-dekreasi
Perkalian x * y Perkalian
x / y Divisi
x % y Sisanya
Penambahan x + y Penambahan, Perangkaian string, kombinasi delegasi
x – y Pengurangan, penghapusan delegasi
Shift x << y Geser kiri
x >> y Geser Kanan
Bitwise AND x & y Bitwise bilangan bulat DAN
Bitwise XOR x ^ y Bilangan bulat bitwise XOR
Bitwise OR x | Y Bitwise bilangan bulat ATAU
Logika AND x && y Boolean logika AND
Logika OR x || y Logika 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 mendukung pewarisan 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 runtimeclass kata kunci, 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 Tinggi dan Lebar, dan properti baca-saja statis bernama NumberOfAreas.

Secara default, runtimeclass disegel, dan turunan darinya tidak diizinkan. Lihat Kelas 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 boleh berisi anggota statis) dengan mengawali definisi kelas runtime dengan static kata kunci. 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 partial kata kunci. 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 Makna
static Kelas tidak memiliki instans. Akibatnya, hanya anggota statis yang diizinkan.
sebagian 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 publik. Itulah sebabnya MIDL 3.0 tidak memerlukan atau mengizinkan kata kunci (berlebihan secara efektif). public

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 Objek (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 berasal dari kelas dasar dikenal sebagai kelas yang dapat dikomposisikan . Dan ada batasan di sekitar kelas yang dapat dikomposisi. Agar aplikasi lulus tes Windows App Certification Kit 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 pewarisan 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 adalah Area, dan kelas dasar Area adalah 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 Memperhitungkan kelas runtime ke dalam file Midl (.idl).

Suatu kelas akan 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 diwarisinya, tetapi tidak dapat menghapus definisi anggota yang diwariskan.

Dalam contoh sebelumnya, Volume mewarisi properti Tinggi dan Lebar dari Area. Jadi, setiap instans Volume berisi tiga properti: Tinggi, Lebar, dan Kedalaman.

Secara umum, aturan resolusi jenis mengharuskan nama jenis sepenuhnya memenuhi syarat saat dirujuk. Pengecualian adalah ketika jenis telah didefinisikan 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 setelah 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 menyatakan dan mendefinisikannya pada implementasi aktual.

Anggota

Anggota kelas adalah anggota statis atau anggota instans. Anggota statis milik 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
Acara 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 Uji di bawah ini mendeklarasikan tiga konstruktor instans; satu tanpa parameter (konstruktor default ), satu yang mengambil parameter Int32 , dan satu yang mengambil dua parameter Ganda (konstruktor parameter ).

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 disegel 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 pengaktor yang menentukan fungsi yang akan dijalankan saat Anda membaca atau menulis properti.

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

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

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

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

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

Selain itu, Anda hanya get dapat menentukan kata kunci 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 set dapat menentukan kata kunci 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 Area sebelumnya (misalnya, kelas Area adalah jenis dalam aplikasi yang Anda kompilasi ulang setiap kali), maka Anda cukup menambahkan set 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 set kata kunci ke deklarasi properti yang ada. Melakukannya mengubah antarmuka biner ke kelas Anda.

Dalam hal ini, tambahkan kata kunci properti set 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 pengaktif pada antarmuka. Urutan kata kunci dapatkan dan atur dalam deklarasi properti menentukan urutan metode dapatkan dan atur aksesor di antarmuka backing.

Pengaktor get sesuai dengan metode tanpa parameter dengan nilai yang dikembalikan dari jenis properti—pemisah 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 static pengubah, 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 adalah void jika itu 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.

Metode kelebihan beban

Metode kelebihan beban memungkinkan beberapa metode di kelas yang sama untuk memiliki nama yang sama selama parameternya berbeda jumlahnya (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 dalam 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 adalah parameter input, yaitu parameter tersebut di-marshal dari pemanggil ke penerima panggilan saja. Kata kunci refpengubah , ref const, dan out dapat ditambahkan untuk memodifikasi arah default marshaling antara penelepon dan penerima panggilan, dan membuat parameter output. 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 mereka tidak terkait, dan efek pengubah ini khusus untuk desain dan fungsi Windows Runtime.

Jenis nilai secara implisit adalah parameter input, dan secara default salinan argumen diteruskan dari pemanggil ke penerima panggilan. Parameter nilai dapat diubah menjadi parameter output dengan out kata kunci; dalam hal ini argumen dinamai sebagai gantinya dari penerima panggilan kembali ke pemanggil 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 ref const kata kunci (bukanconst ref), yang menandai parameter struct sebagai parameter input, tetapi menginstruksikan marshaler untuk meneruskan pointer ke penyimpanan struct, alih-alih meneruskan salinan lengkap struct. Namun perhatikan bahwa struktur tidak dapat diubah; pointer secara konseptual adalah penunjuk const. Tidak ada tinju yang terlibat. Ini adalah pilihan praktis saat menerima nilai sebesar Matrix4x4, misalnya.

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

Jenis referensi juga secara implisit memasukkan parameter, yang berarti bahwa pemanggil 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 sebagai parameter output dengan out kata kunci . Dalam hal ini peran dibalik; penerima panggilan adalah orang yang mengalokasikan objek dan mengembalikannya kembali ke pemanggil. Sekali lagi, ref kata kunci 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 marsekal untuk parameter nilai dan parameter referensi:

Perilaku Dialokasikan oleh Kata kunci Jenis Keterangan
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—semuanya berjenis 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 ref kata kunci ke parameter; dalam pengaturan tersebut, 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 array penerima 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
"Lulus array" (tidak ada) Pemanggil Baca-saja
"Isi array" ref Pemanggil Hanya tulis
"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 static dideklarasikan dengan awalan pengubah 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 dinyatakan 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 metode get properti .

Metode statis GetNextSerialNo dan SetNextSerialNo dapat mengakses anggota statis nomor seri internal berikutnya yang tersedia 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 yang pemanggilannya terjadi menentukan implementasi metode aktual untuk dipanggil.

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

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

Acara

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

Anda mendeklarasikan peristiwa menggunakan event kata kunci , 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: metode add , yang dipanggil klien untuk menambahkan penanganan aktivitas ke sumber, dan metode hapus , 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.

Delegasikan

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 delegate kata kunci .

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

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 membahas struktur, Anda juga dapat mengganti parameter WindowSizeChangedEventArgs dengan jenis argumen peristiwa Anda sendiri.

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

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

Lihat juga Delegasi yang mengembalikan HRESULT.

Struct

Struktur adalah struktur data yang dapat berisi anggota data (bidang). Tetapi, 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 yang diimplementasikan sebagai kelas, 101 objek terpisah dibuat: satu untuk objek array itu sendiri; dan satu untuk masing-masing elemen 100 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 menjadikan Point sebagai struct, bukan kelas.

struct Point
{
    Int32 x;
    Int32 y;
};

Sekarang, hanya satu objek yang dibuat—objek array itu sendiri. Elemen Titik disimpan sejalan 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 mendefinisikan 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 menerapkan IComboBox, juga mengimplementasikan ITextBox dan IListBox. Selain itu, kelas yang menerapkan IComboBox juga harus mengimplementasikan IControl. Itu karena ITextBox dan IListBoxmemerlukannya.

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 mengimplementasikan 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 umum (dan dengan demikian polimorfik) melalui antarmuka umum tersebut.

Catatan

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

Enum

Jenis enum (atau jenis enumerasi, atau enumerasi) adalah jenis nilai yang berbeda dengan sekumpulan konstanta bernama. Contoh berikut mendefinisikan dan menggunakan jenis enum bernama Color dengan tiga nilai konstan: Merah, Hijau, dan Biru.

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 enum yang mendasar. Jenis enum yang mendasar adalah Int32 atau UInt32.

Windows Runtime mendukung dua jenis enum: enum normal , dan enum bendera . Enum dari jenis normal mengekspresikan serangkaian 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 [flags] atribut yang diterapkan. Dalam hal ini, jenis enum yang mendasar adalah UInt32. [flags] Ketika atribut tidak ada (enum normal), jenis enum yang mendasar adalah Int32. Tidak dimungkinkan 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 dasarnya. Kumpulan nilai yang dapat diambil oleh jenis enum tidak dibatasi oleh anggota enum yang dinyatakan.

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

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 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 UInt32 yang 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 protected akses. 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 yang mengelilingi 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 ada di namespace Windows.Foundation .

Seperti yang ditunjukkan pada contoh pertama, Anda menggunakan [attributeusage(<target>)] atribut pada definisi atribut Anda. Nilai target yang valid adalah target_all, , target_enumtarget_delegate, 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 dengan 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]: expecting > or, near ">>".

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

Sebagai gantinya, sisipkan spasi di 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]: expecting > or, near "[". 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.