Tester si l'objet implémente l'interface

355

Quelle est la manière la plus simple de tester si un objet implémente une interface donnée en C #? (Réponse à cette question en Java )

JoshRivers
la source

Réponses:

570
if (object is IBlah)

ou

IBlah myTest = originalObject as IBlah

if (myTest != null)
Robert C. Barth
la source
85
+1 Le second est meilleur parce que vous finirez probablement par avoir besoin de lancer ensuite avec le premier vous donnant ainsi deux lancers ("est" puis un casting explicite). Avec la deuxième approche, vous ne lancez qu'une seule fois.
Andrew Hare
51
@Andrew: +1; Il est temps pour le lien vers le blog classique Double-Casting AntiPattern de Julian M Bucknall .
Jeroen Wiert Pluimers
1
L'optimisation ne vous fera probablement pas lancer deux fois dans le premier cas?
BuZz
1
@Joreen, ce lien manque un point si vous travaillez avec une structure que vous ne pouvez pas utiliser "as" car il ne contiendra pas de null qui est ce que le "as" essaie de retourner, dans ce cas, vous devez passer par un nullable classe comme int?, mais ce n'est pas un problème si vous ne travaillez qu'au niveau de l'interface car ce sont toujours des types de référence
MikeT
46
Depuis C # 6.0:if (object is IBlah iblah) { iblah.SomeMethod(); }
Knelis
224

L'utilisation des opérateurs isou asest la bonne façon si vous connaissez le type d'interface au moment de la compilation et avez une instance du type que vous testez. Quelque chose que personne d'autre ne semble avoir mentionné est Type.IsAssignableFrom:

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

Je pense que c'est beaucoup plus net que de regarder à travers le tableau retourné par GetInterfaceset a l'avantage de travailler aussi pour les classes.

Andrew Kennan
la source
J'essaie de déterminer si un type implémente une instanciation d'IList. J'utilise "typeof (IList <>). IsAssignableFrom (someType)" mais cela ne fonctionne pas.
KeyboardDrummer
3
Vous feriez mieux de poser cette question dans une autre question. Si someType est le type des éléments de la liste, vous pourriez avoir besoin de typeof (IList <>). MakeGenericType (someType). Si someType est le type de liste, vous devez regarder Type.GetGenericArguments et Type.GetGenericTypeDefinition.
Andrew Kennan
Je l'utilise pour la vérification de type dans un système de plugins. Il peut être utilisé dans des situations où une instance de l'objet n'existe pas encore. Mais j'utilise à la fois ce style et celui de Robert en fonction de ce que je fais, j'ai donc voté dans les deux sens.
James
Il s'agit d'un commentaire plus ancien, mais pour répondre à la question de @ Steenreem, utilisez typeof(IList).IsAssignableFrom(someType)sans <>.
saluce
Cette méthode fonctionne même avec les opérateurs de conversion et si des convertisseurs de type sont impliqués
Harald Coppoolse
22

Par exemple:

if (obj is IMyInterface) {}

Pour la classe:

Vérifiez si typeof(MyClass).GetInterfaces()contient l'interface.

Rauhotz
la source
1
if (Array.IndexOf (typeof (MyClass) .GetInterfaces (), typeof (IMyInterface))! = -1) {...}
Constantin
2
ou: if (typeof (MyClass) .GetInterfaces (). Contains (typeof (IMyInterface))) {...}
Lance Fisher
17

Si vous souhaitez utiliser l'objet transtypé après la vérification:
Depuis C # 7.0:

if (obj is IMyInterface myObj)

C'est la même chose que

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

Voir Docs .NET: correspondance de modèle avec ismodèle de type #

Martin Schneider
la source
16

Une variante de la réponse de @ AndrewKennan que j'ai fini par utiliser récemment pour les types obtenus lors de l'exécution:

if (serviceType.IsInstanceOfType(service))
{
    // 'service' does implement the 'serviceType' type
}
célèbregarkin
la source
7

Ce message est une bonne réponse.

public interface IMyInterface {}

public class MyType : IMyInterface {}

Voici un exemple simple:

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

ou

typeof(MyType).GetInterfaces().Contains(typeof(IMyInterface))
eliasetm
la source
3

En plus de tester en utilisant l'opérateur "is", vous pouvez décorer vos méthodes pour vous assurer que les variables qui lui sont passées implémentent une interface particulière, comme ceci:

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

Je ne sais pas dans quelle version de .Net cela a été implémenté, donc cela peut ne pas fonctionner dans votre version.

jamesmillerio
la source
2
.net 2.0 a ajouté des génériques.
Robert
C'est la seule vérification à la compilation dans ce fil, merci.
Dustin Malone
2

Ce qui a fonctionné pour moi, c'est:

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

Dutchman078
la source
1

Récemment, j'ai essayé d'utiliser la réponse d'Andrew Kennan et cela n'a pas fonctionné pour moi pour une raison quelconque. Je l'ai utilisé à la place et cela a fonctionné (note: l'écriture de l'espace de noms peut être nécessaire).

if (typeof(someObject).GetInterface("MyNamespace.IMyInterface") != null)
jahu
la source
2
Si vous finissez par emprunter cette voie, je ne suis pas un fan des cordes magiques, donc je changerais au minimum cela pour être typeof (IMyInterface) .Name au lieu de "MyNamespace.IMyInterface". Aide à en faire une preuve de refactorisation de nom en prime.
greyalien007
0

j'ai utilisé

Assert.IsTrue(myObject is ImyInterface);

pour un test dans mon test unitaire qui teste que myObject est un objet qui a implémenté mon interface ImyInterface.

iamrcw
la source
-1

J'ai eu une situation où je passais une variable à une méthode et ne savais pas si ça allait être une interface ou un objet.

Les objectifs étaient les suivants:

  1. Si item est une interface, instanciez un objet basé sur cette interface avec l'interface étant un paramètre dans l'appel du constructeur.
  2. Si l'élément est un objet, retournez une valeur nulle, car le constructeur de mes appels attend une interface et je ne voulais pas que le code soit utilisé.

J'ai atteint cet objectif avec les éléments suivants:

    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
la source
-12

Cela devrait fonctionner:

MyInstace.GetType().GetInterfaces();

Mais sympa aussi:

if (obj is IMyInterface)

Ou même (pas très élégant):

if (obj.GetType() == typeof(IMyInterface))
Yoann. B
la source
9
La vérification de l'égalité avec typeof (IMyInterface) échouera toujours. Voté.
Jay Bazuzi
Droite. Il n'y a aucune instance d'une interface.
Rauhotz