Bagikan melalui


Refleksi dan tipe generik

Dari sudut pandang pantulan, perbedaan antara jenis generik dan jenis biasa adalah bahwa jenis generik telah dikaitkan dengannya sekumpulan parameter jenis (jika itu adalah definisi jenis generik) atau argumen jenis (jika itu adalah jenis yang dibangun). Metode generik berbeda dari metode biasa dengan cara yang sama.

Ada dua kunci untuk memahami bagaimana refleksi menangani tipe dan metode generik.

  • Parameter jenis definisi jenis generik dan definisi metode generik diwakili oleh instans Type kelas.

    Nota

    Banyak properti dan metode dari Type memiliki perilaku berbeda ketika objek Type mewakili parameter tipe generik. Perbedaan ini didokumenkan dalam artikel properti dan metode. Misalnya, lihat IsAutoClass dan DeclaringType. Selain itu, beberapa anggota hanya valid ketika Type objek mewakili parameter jenis generik. Misalnya, lihat GetGenericTypeDefinition.

  • Jika instans Type mewakili jenis generik, maka instans tersebut menyertakan array jenis yang mewakili parameter jenis (untuk definisi jenis generik) atau argumen jenis (untuk jenis yang dibangun). Hal yang sama berlaku untuk instans MethodInfo kelas yang mewakili metode generik.

Refleksi menyediakan metode Type dan MethodInfo yang memungkinkan Anda mengakses array parameter tipe, dan menentukan apakah instans Type mewakili parameter tipe atau tipe aktual.

Sebagai contoh kode yang menunjukkan metode yang dibahas di sini, lihatlah Cara: Memeriksa dan Membuat Instans Jenis Generik dengan Refleksi.

Diskusi berikut mengasumsikan keakraban dengan terminologi generik, seperti perbedaan antara parameter jenis dan argumen dan jenis yang dibangun terbuka atau tertutup. Untuk informasi selengkapnya, lihat Generik.

Apakah ini jenis atau metode generik?

Saat Anda menggunakan pantulan untuk memeriksa jenis yang tidak diketahui, yang diwakili oleh instans Type, gunakan IsGenericType properti untuk menentukan apakah jenis yang tidak diketahui bersifat generik. Ini mengembalikan true jika jenisnya generik. Demikian pula, ketika Anda memeriksa metode yang tidak diketahui, yang diwakili oleh instans MethodInfo kelas, gunakan IsGenericMethod properti untuk menentukan apakah metode tersebut generik.

Apakah ini jenis generik atau definisi metode?

Gunakan properti IsGenericTypeDefinition untuk menentukan apakah objek Type mewakili definisi tipe generik, dan gunakan metode IsGenericMethodDefinition untuk menentukan apakah objek MethodInfo mewakili definisi metode generik.

Definisi jenis dan metode generik adalah pola dasar tempat jenis yang dapat diinstansiasi dibuat. Jenis generik dalam pustaka .NET, seperti Dictionary<TKey,TValue>, adalah definisi jenis generik.

Apakah jenis atau metode terbuka atau tertutup?

Jenis atau metode generik terselesaikan jika jenis instansiasi telah digantikan untuk semua parameter jenisnya, termasuk semua parameter jenis dari semua jenis yang melingkupi. Anda hanya dapat membuat objek dari jenis generik jika jenis tersebut tertutup. Properti Type.ContainsGenericParameters akan mengembalikan true jika jenisnya terbuka. Untuk metode, metode MethodBase.ContainsGenericParameters melakukan fungsi yang sama.

Hasilkan jenis generik tertutup

Setelah Anda memiliki jenis generik atau definisi metode, gunakan MakeGenericType metode untuk membuat jenis generik tertutup atau MakeGenericMethod metode untuk membuat MethodInfo metode generik tertutup.

Mendapatkan jenis generik atau definisi metode

Jika Anda memiliki jenis atau metode generik terbuka yang bukan jenis generik atau definisi metode, Anda tidak dapat membuat instansnya dan Anda tidak dapat menyediakan parameter jenis yang hilang. Anda harus memiliki jenis generik atau definisi metode. GetGenericTypeDefinition Gunakan metode untuk mendapatkan definisi jenis generik atau GetGenericMethodDefinition metode untuk mendapatkan definisi metode generik.

Misalnya, jika Anda memiliki objek yang Type mewakili Dictionary<int, string> dan Anda ingin membuat jenis Dictionary<string, MyClass>, Anda dapat menggunakan GetGenericTypeDefinition metode untuk mendapatkan Type representasi Dictionary<TKey, TValue> dan kemudian menggunakan MakeGenericType metode untuk menghasilkan Type representasi Dictionary<int, MyClass>.

Untuk contoh jenis generik terbuka yang bukan jenis generik, lihat Parameter jenis atau argumen jenis.

Memeriksa argumen jenis dan parameter jenis

Gunakan metode Type.GetGenericArguments untuk mendapatkan array objek Type yang mewakili parameter tipe atau argumen tipe dari tipe generik, dan gunakan metode MethodInfo.GetGenericArguments untuk melakukan hal yang sama pada metode generik.

Setelah Anda tahu bahwa objek Type mewakili parameter tipe, ada banyak pertanyaan tambahan yang dapat dijawab melalui refleksi. Anda dapat menentukan sumber parameter jenis, posisinya, dan batasannya.

Ketik parameter atau ketik argumen

Untuk menentukan apakah elemen tertentu dari array adalah parameter jenis atau argumen jenis, gunakan IsGenericParameter properti . Properti IsGenericParameter adalah true jika elemen adalah parameter jenis.

Jenis generik dapat terbuka tanpa menjadi definisi jenis generik, dalam hal ini memiliki campuran argumen jenis dan parameter jenis. Misalnya, dalam kode berikut, kelas D berasal dari jenis yang dibuat dengan mengganti parameter D jenis pertama untuk parameter jenis kedua dari B.

class B<T, U> {}
class D<V, W> : B<int, V> {}
Class B(Of T, U)
End Class
Class D(Of V, W)
    Inherits B(Of Integer, V)
End Class

Jika Anda memperoleh sebuah objek Type yang mewakili D<V, W> dan menggunakan properti BaseType untuk mendapatkan jenis dasarnya, hasilnya adalah type B<int, V> yang terbuka, tetapi bukan definisi jenis generik.

Sumber parameter generik

Parameter jenis generik mungkin berasal dari jenis yang Anda periksa, dari jenis yang tertutup, atau dari metode generik. Anda dapat menentukan sumber parameter jenis generik sebagai berikut:

  • Pertama, gunakan DeclaringMethod properti untuk menentukan apakah parameter jenis berasal dari metode generik. Jika nilai properti bukan referensi null, maka sumbernya adalah metode generik.
  • Jika sumber bukan metode generik, gunakan properti DeclaringType untuk menentukan jenis generik tempat parameter jenis generik berada.

Jika parameter jenis milik metode generik, DeclaringType properti mengembalikan jenis yang mendeklarasikan metode generik, yang tidak relevan.

Posisi parameter generik

Dalam situasi yang jarang terjadi, perlu untuk menentukan posisi parameter tipe dalam daftar parameter tipe kelas yang mendeklarasikannya. Misalnya, Anda memiliki objek Type yang mewakili jenis B<int, V> dari contoh sebelumnya. Metode GetGenericArguments memberi Anda daftar jenis argumen, dan ketika Anda memeriksa V, Anda dapat menggunakan properti DeclaringMethod dan DeclaringType untuk menemukan dari mana asalnya. Anda kemudian dapat menggunakan properti GenericParameterPosition untuk menentukan posisinya dalam daftar parameter jenis tempat properti tersebut didefinisikan. Dalam contoh ini, V berada pada posisi 0 (nol) dalam daftar jenis parameter di mana ia didefinisikan.

Jenis dasar dan batasan antarmuka

GetGenericParameterConstraints Gunakan metode untuk mendapatkan batasan jenis dasar dan batasan antarmuka parameter jenis. Urutan elemen array tidak signifikan. Elemen mewakili batasan antarmuka jika merupakan jenis antarmuka.

Atribut parameter umum

Properti GenericParameterAttributes mengambil nilai GenericParameterAttributes yang menunjukkan variasi (kovariansi atau kontravariansi) dan batasan khusus dari parameter tipe.

Kovarian dan kontravarian

Untuk menentukan apakah parameter jenis bersifat kovarian atau kontravarian, terapkan mask GenericParameterAttributes.VarianceMask pada nilai GenericParameterAttributes yang dikembalikan oleh properti GenericParameterAttributes. Jika hasilnya adalah GenericParameterAttributes.None, parameter tipe tidak berubah. Untuk informasi selengkapnya, lihat Kovariansi dan Kontravariansi.

Batasan khusus

Untuk menentukan batasan khusus parameter jenis, terapkan GenericParameterAttributes.SpecialConstraintMask masker ke GenericParameterAttributes nilai yang dikembalikan oleh GenericParameterAttributes properti . Jika hasilnya adalah GenericParameterAttributes.None, tidak ada batasan khusus. Parameter jenis dapat dibatasi menjadi jenis referensi, menjadi jenis nilai yang tidak dapat diubah ke null, dan memiliki konstruktor tanpa parameter.

Ketetapan

Untuk melihat tabel kondisi invarian istilah umum dalam konteks refleksi tipe generik, lihat Type.IsGenericType. Untuk istilah tambahan yang berkaitan dengan metode generik, lihat MethodBase.IsGenericMethod.