Uji apakah objek mengimplementasikan antarmuka


355

Apa cara paling sederhana untuk menguji jika suatu objek mengimplementasikan antarmuka yang diberikan dalam C #? (Jawab untuk pertanyaan ini di Jawa )

Jawaban:


570
if (object is IBlah)

atau

IBlah myTest = originalObject as IBlah

if (myTest != null)

85
+1 Yang kedua lebih baik karena Anda mungkin pada akhirnya akan perlu melakukan casting dengan yang pertama sehingga memberi Anda dua gips ("adalah" dan kemudian pemeran eksplisit). Dengan pendekatan kedua Anda hanya melemparkan sekali.
Andrew Hare

51
@Andrew: +1; Sekali lagi untuk tautan ke posting blog klasik Double-Casting AntiPattern oleh Julian M Bucknall .
Jeroen Wiert Pluimers

1
Optimasi mungkin tidak akan membuat Anda melakukan dua kali dalam kasus pertama?
BuZz

1
@Joreen, tautan itu kehilangan satu titik jika Anda bekerja dengan struktur yang tidak dapat Anda gunakan "sebagai" karena tidak akan menyimpan nol yang mana "sebagai" mencoba untuk kembali, dalam hal ini Anda harus melalui nullable kelas seperti int ?, meskipun bukan masalah jika Anda hanya bekerja di level antarmuka karena mereka selalu menjadi tipe referensi
MikeT

46
Sejak C # 6.0:if (object is IBlah iblah) { iblah.SomeMethod(); }
Knelis

224

Menggunakan isatau asoperator adalah cara yang benar jika Anda mengetahui jenis antarmuka pada waktu kompilasi dan memiliki instance dari jenis yang Anda uji. Sesuatu yang tampaknya tidak disebutkan oleh orang lain adalah Type.IsAssignableFrom:

if( typeof(IMyInterface).IsAssignableFrom(someOtherType) )
{
}

Saya pikir ini jauh lebih rapi daripada melihat melalui array yang dikembalikan oleh GetInterfacesdan memiliki keuntungan bekerja untuk kelas juga.


Saya mencoba untuk menentukan apakah suatu tipe mengimplementasikan beberapa Instansiasi IList. Saya menggunakan "typeof (IList <>). IsAssignableFrom (someType)" tetapi itu tidak berfungsi.
KeyboardDrummer

3
Anda mungkin lebih baik menanyakan hal ini dalam pertanyaan lain. Jika someType adalah jenis elemen daftar, Anda bisa membutuhkan typeof (IList <>). MakeGenericType (someType). Jika someType adalah tipe daftar, Anda harus melihat di Type.GetGenericArguments and Type.GetGenericTypeDefinition.
Andrew Kennan

Saya menggunakan ini untuk memeriksa jenis dalam sistem plugin. Ini dapat digunakan dalam situasi di mana instance objek belum ada. Tapi saya menggunakan gaya ini dan gaya Robert tergantung pada apa yang saya lakukan sehingga saya memilih kedua cara.
James

Ini adalah komentar yang lebih lama, tetapi untuk menjawab pertanyaan @ Steenreem, gunakan typeof(IList).IsAssignableFrom(someType), tanpa <>.
bernilai

Metode ini bahkan bekerja dengan operator konversi dan jika TypeConverters terlibat
Harald Coppoolse

22

Sebagai contoh:

if (obj is IMyInterface) {}

Untuk kelas:

Periksa apakah typeof(MyClass).GetInterfaces()mengandung antarmuka.


1
if (Array.IndexOf (typeof (MyClass) .GetInterfaces (), typeof (IMyInterface))! = -1) {...}
Constantin

2
atau: if (typeof (MyClass) .GetInterfaces (). Berisi (typeof (IMyInterface)))) {...}
Lance Fisher


16

Variasi jawaban @ AndrewKennan akhirnya saya gunakan untuk jenis yang diperoleh saat runtime:

if (serviceType.IsInstanceOfType(service))
{
    // 'service' does implement the 'serviceType' type
}

7

Posting ini adalah jawaban yang bagus.

public interface IMyInterface {}

public class MyType : IMyInterface {}

Ini adalah contoh sederhana:

typeof(IMyInterface).IsAssignableFrom(typeof(MyType))

atau

typeof(MyType).GetInterfaces().Contains(typeof(IMyInterface))

3

Selain pengujian menggunakan operator "is", Anda dapat menghias metode Anda untuk memastikan bahwa variabel yang dikirimkan ke sana mengimplementasikan antarmuka tertentu, seperti:

public static void BubbleSort<T>(ref IList<T> unsorted_list) where T : IComparable
{
     //Some bubbly sorting
}

Saya tidak yakin versi Net mana ini diimplementasikan sehingga mungkin tidak bekerja dalam versi Anda.


2
.net 2.0 menambahkan obat generik.
Robert C. Barth

Ini adalah satu - satunya pemeriksaan waktu kompilasi di utas ini, terima kasih.
Dustin Malone

2

Apa yang berhasil untuk saya adalah:

Assert.IsNotNull(typeof (YourClass).GetInterfaces().SingleOrDefault(i => i == typeof (ISomeInterface)));


1

Baru-baru ini saya mencoba menggunakan jawaban Andrew Kennan dan itu tidak berhasil untuk beberapa alasan. Saya menggunakan ini sebagai gantinya dan itu berhasil (catatan: menulis namespace mungkin diperlukan).

if (typeof(someObject).GetInterface("MyNamespace.IMyInterface") != null)

2
Jika Anda berakhir dengan rute ini, saya bukan penggemar string sihir, jadi saya minimal akan mengubah ini menjadi typeof (IMyInterface). Nama bukan "MyNamespace.IMyInterface". Membantu menjadikannya nama bukti refactoring sebagai bonus.
greyalien007

0

Saya menggunakan

Assert.IsTrue(myObject is ImyInterface);

untuk pengujian dalam unit test saya yang menguji bahwa myObject adalah objek yang telah mengimplementasikan antarmuka saya ImyInterface.


-1

Saya memiliki situasi di mana saya mengirimkan variabel ke suatu metode dan tidak yakin apakah itu akan menjadi antarmuka atau objek.

Tujuannya adalah:

  1. Jika item adalah antarmuka, instantiate objek berdasarkan antarmuka itu dengan antarmuka menjadi parameter dalam panggilan konstruktor.
  2. Jika item tersebut adalah objek, kembalikan nilai nol karena konstuktor untuk panggilan saya mengharapkan antarmuka dan saya tidak ingin kode tersebut dimasukkan.

Saya mencapai ini dengan yang berikut:

    if(!typeof(T).IsClass)
    {
       // If your constructor needs arguments...
       object[] args = new object[] { my_constructor_param };
       return (T)Activator.CreateInstance(typeof(T), args, null);
    }
    else
       return default(T);

-12

Ini seharusnya bekerja:

MyInstace.GetType().GetInterfaces();

Tapi bagus juga:

if (obj is IMyInterface)

Atau bahkan (tidak terlalu elegan):

if (obj.GetType() == typeof(IMyInterface))

9
Memeriksa kesetaraan untuk mengetik (IMyInterface) akan selalu gagal. Diturunkan.
Jay Bazuzi

Baik. Tidak ada contoh antarmuka.
Rauhotz
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.