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 )

JoshRivers
sumber

Jawaban:

570
if (object is IBlah)

atau

IBlah myTest = originalObject as IBlah

if (myTest != null)
Robert C. Barth
sumber
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.

Andrew Kennan
sumber
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.

Rauhotz
sumber
1
if (Array.IndexOf (typeof (MyClass) .GetInterfaces (), typeof (IMyInterface))! = -1) {...}
Constantin
2
atau: if (typeof (MyClass) .GetInterfaces (). Berisi (typeof (IMyInterface)))) {...}
Lance Fisher
17

Jika Anda ingin menggunakan objek typecasted setelah centang:
Sejak C # 7.0:

if (obj is IMyInterface myObj)

Ini sama dengan

IMyInterface myObj = obj as IMyInterface;
if (myObj != null)

Lihat .NET Docs: Pencocokan pola dengan ispola # Type

Martin Schneider
sumber
16

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

if (serviceType.IsInstanceOfType(service))
{
    // 'service' does implement the 'serviceType' type
}
gin terkenal
sumber
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))
eliasetm
sumber
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.

jamesmillerio
sumber
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)));

Dutchman078
sumber
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)
jahu
sumber
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.

iamrcw
sumber
-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);
Anthony Tristan
sumber
-12

Ini seharusnya bekerja:

MyInstace.GetType().GetInterfaces();

Tapi bagus juga:

if (obj is IMyInterface)

Atau bahkan (tidak terlalu elegan):

if (obj.GetType() == typeof(IMyInterface))
Yoann. B
sumber
9
Memeriksa kesetaraan untuk mengetik (IMyInterface) akan selalu gagal. Diturunkan.
Jay Bazuzi
Baik. Tidak ada contoh antarmuka.
Rauhotz