Testen Sie, ob das Objekt die Schnittstelle implementiert


355

Was ist der einfachste Weg zu testen, ob ein Objekt eine bestimmte Schnittstelle in C # implementiert? (Antwort auf diese Frage in Java )

Antworten:


569
if (object is IBlah)

oder

IBlah myTest = originalObject as IBlah

if (myTest != null)

85
+1 Die zweite ist besser, weil Sie wahrscheinlich später mit der ersten wirken müssen, wodurch Sie zwei Würfe erhalten ("ist" und dann eine explizite Besetzung). Beim zweiten Ansatz haben Sie nur einmal gewirkt.
Andrew Hare

51
@ Andrew: +1; Es ist wieder Zeit für den Link zum klassischen Double-Casting AntiPattern-Blogbeitrag von Julian M Bucknall .
Jeroen Wiert Pluimers

1
Bei der Optimierung werden Sie im ersten Fall wahrscheinlich nicht zweimal gecastet?
BuZz

1
@Joreen, dieser Link verfehlt einen Punkt, wenn Sie mit einer Struktur arbeiten, die Sie nicht als "as" verwenden können, da sie keine Null enthält, was das "as" versucht zurückzugeben. In diesem Fall müssen Sie eine Nullable durchlaufen Klasse wie int?, obwohl kein Problem, wenn Sie nur auf der Schnittstellenebene arbeiten, da es sich immer um Referenztypen handelt
MikeT

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

224

Die Verwendung der Operatoren isoder asist der richtige Weg, wenn Sie den Schnittstellentyp zur Kompilierungszeit kennen und über eine Instanz des zu testenden Typs verfügen. Etwas, das sonst niemand erwähnt zu haben scheint, ist Type.IsAssignableFrom:

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

Ich denke, das ist viel ordentlicher als das Durchsehen des von zurückgegebenen Arrays GetInterfacesund hat den Vorteil, auch für Klassen zu arbeiten.


Ich versuche festzustellen, ob ein Typ eine Instanziierung von IList implementiert. Ich verwende "typeof (IList <>). IsAssignableFrom (someType)", aber das funktioniert nicht.
KeyboardDrummer

3
Vielleicht ist es besser, dies in einer anderen Frage zu stellen. Wenn someType der Typ der Listenelemente ist, benötigen Sie möglicherweise typeof (IList <>). MakeGenericType (someType). Wenn someType der Listentyp ist, sollten Sie sich Type.GetGenericArguments und Type.GetGenericTypeDefinition ansehen.
Andrew Kennan

Ich benutze dies für die Typprüfung in einem Plugin-System. Es kann in Situationen verwendet werden, in denen eine Instanz des Objekts noch nicht vorhanden ist. Aber ich benutze sowohl diesen als auch Roberts Stil, je nachdem, was ich tue, habe ich in beide Richtungen abgestimmt.
James

Dies ist ein älterer Kommentar, aber um die Frage von @ Steenreem zu beantworten, verwenden Sie typeof(IList).IsAssignableFrom(someType), ohne die <>.
Saluce

Diese Methode funktioniert sogar mit Konvertierungsoperatoren und wenn TypeConverters beteiligt sind
Harald Coppoolse

22

Für die Instanz:

if (obj is IMyInterface) {}

Für die Klasse:

Überprüfen Sie, ob typeof(MyClass).GetInterfaces()die Schnittstelle enthalten ist.


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

2
oder: if (typeof (MyClass) .GetInterfaces (). Contains (typeof (IMyInterface))) {...}
Lance Fisher


16

Eine Variation von @ AndrewKennans Antwort, die ich kürzlich für zur Laufzeit erhaltene Typen verwendet habe:

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

7

Dieser Beitrag ist eine gute Antwort.

public interface IMyInterface {}

public class MyType : IMyInterface {}

Dies ist ein einfaches Beispiel:

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

oder

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

3

Zusätzlich zum Testen mit dem Operator "is" können Sie Ihre Methoden dekorieren, um sicherzustellen, dass an ihn übergebene Variablen eine bestimmte Schnittstelle implementieren, z. B.:

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

Ich bin nicht sicher, in welcher Version von .Net dies implementiert wurde, sodass es in Ihrer Version möglicherweise nicht funktioniert.


2
.net 2.0 hat Generika hinzugefügt.
Robert C. Barth

Dies ist die einzige Überprüfung zur Kompilierungszeit in diesem Thread, danke.
Dustin Malone

2

Was für mich funktioniert hat ist:

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


1

Kürzlich habe ich versucht, Andrew Kennans Antwort zu verwenden, und es hat aus irgendeinem Grund bei mir nicht funktioniert. Ich habe dies stattdessen verwendet und es hat funktioniert (Hinweis: Möglicherweise ist das Schreiben des Namespace erforderlich).

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

2
Wenn Sie diesen Weg gehen, bin ich kein Fan von magischen Strings, daher würde ich dies zumindest in typeof (IMyInterface) .Name anstelle von "MyNamespace.IMyInterface" ändern. Hilft dabei, den Refactoring-Beweis als Bonus zu benennen.
greyalien007

0

ich benutzte

Assert.IsTrue(myObject is ImyInterface);

für einen Test in meinem Unit-Test, der testet, dass myObject ein Objekt ist, das meine Schnittstelle ImyInterface implementiert hat.


-1

Ich hatte eine Situation, in der ich eine Variable an eine Methode übergab und nicht sicher war, ob es sich um eine Schnittstelle oder ein Objekt handeln würde.

Die Ziele waren:

  1. Wenn item eine Schnittstelle ist, instanziieren Sie ein Objekt basierend auf dieser Schnittstelle, wobei die Schnittstelle ein Parameter im Konstruktoraufruf ist.
  2. Wenn das Element ein Objekt ist, geben Sie eine Null zurück, da der Konstruktor für meine Aufrufe eine Schnittstelle erwartet und ich nicht wollte, dass der Code tankt.

Ich habe dies mit folgendem erreicht:

    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

Das sollte funktionieren :

MyInstace.GetType().GetInterfaces();

Aber auch schön:

if (obj is IMyInterface)

Oder sogar (nicht sehr elegant):

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

9
Die Überprüfung der Gleichheit mit typeof (IMyInterface) schlägt immer fehl. Abgestimmt.
Jay Bazuzi

Recht. Es gibt keine Instanzen einer Schnittstelle.
Rauhotz
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.