Probar si el objeto implementa la interfaz

355

¿Cuál es la forma más simple de probar si un objeto implementa una interfaz dada en C #? (Respuesta a esta pregunta en Java )

JoshRivers
fuente

Respuestas:

570
if (object is IBlah)

o

IBlah myTest = originalObject as IBlah

if (myTest != null)
Robert C. Barth
fuente
85
+1 El segundo es mejor porque probablemente terminarás necesitando lanzar después con el primero, dándote dos lanzamientos ("es" y luego un lanzamiento explícito). Con el segundo enfoque solo lanzas una vez.
Andrew Hare el
51
@Andrew: +1; Una vez más, el enlace a la clásica publicación de blog Anti-Patrón de doble fundición de Julian M Bucknall .
Jeroen Wiert Pluimers
1
¿La optimización probablemente no te hará lanzar dos veces en el primer caso?
BuZz
1
@Joreen, ese enlace pierde un punto si está trabajando con una estructura que no puede usar "como" porque no contendrá un valor nulo, que es lo que el "como" intenta devolver, en ese caso debe pasar por un elemento anulable class like int ?, aunque no es un problema si solo trabajas a nivel de interfaz, ya que siempre son tipos de referencia
MikeT
46
Desde C # 6.0:if (object is IBlah iblah) { iblah.SomeMethod(); }
Knelis
224

Usar los operadores iso ases la forma correcta si conoce el tipo de interfaz en tiempo de compilación y tiene una instancia del tipo que está probando. Algo que nadie más parece haber mencionado es Type.IsAssignableFrom:

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

Creo que esto es mucho más ordenado que mirar a través de la matriz devuelta GetInterfacesy también tiene la ventaja de trabajar para las clases.

Andrew Kennan
fuente
Estoy tratando de determinar si un tipo implementa alguna instanciación de IList. Estoy usando "typeof (IList <>). IsAssignableFrom (someType)" pero eso no funciona.
KeyboardDrummer
3
Es mejor que hagas esto en otra pregunta. Si someType es el tipo de elementos de la lista, podría necesitar typeof (IList <>). MakeGenericType (someType). Si someType es el tipo de lista, debe mirar Type.GetGenericArguments y Type.GetGenericTypeDefinition.
Andrew Kennan
Lo uso para la verificación de tipos en un sistema de complementos. Se puede utilizar en situaciones en las que todavía no existe una instancia del objeto. Pero uso tanto este estilo como el de Robert dependiendo de lo que estoy haciendo, así que voté en ambos sentidos.
James
Este es un comentario anterior, pero para responder a la pregunta de @ Steenreem, use typeof(IList).IsAssignableFrom(someType), sin el <>.
Salse
Este método incluso funciona con operadores de conversión y si los TypeConverters están involucrados
Harald Coppoolse
22

Por ejemplo:

if (obj is IMyInterface) {}

Para la clase:

Compruebe si typeof(MyClass).GetInterfaces()contiene la interfaz.

Rauhotz
fuente
1
if (Array.IndexOf (typeof (MyClass) .GetInterfaces (), typeof (IMyInterface))! = -1) {...}
Constantin
2
o: if (typeof (MyClass) .GetInterfaces (). Contiene (typeof (IMyInterface))) {...}
Lance Fisher el
17

Si desea usar el objeto con tipografía después de la verificación:
Desde C # 7.0:

if (obj is IMyInterface myObj)

Esto es lo mismo que

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

Consulte Documentos de .NET: coincidencia de patrones con is# Tipo de patrón

Martin Schneider
fuente
16

Una variación de la respuesta de @ AndrewKennan que terminé usando recientemente para los tipos obtenidos en tiempo de ejecución:

if (serviceType.IsInstanceOfType(service))
{
    // 'service' does implement the 'serviceType' type
}
calabaza famosa
fuente
7

Esta publicación es una buena respuesta.

public interface IMyInterface {}

public class MyType : IMyInterface {}

Esta es una muestra simple:

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

o

typeof(MyType).GetInterfaces().Contains(typeof(IMyInterface))
eliasetm
fuente
3

Además de probar con el operador "es", puede decorar sus métodos para asegurarse de que las variables que se le pasen implementen una interfaz particular, de esta manera:

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

No estoy seguro de qué versión de .Net se implementó, por lo que es posible que no funcione en su versión.

jamesmillerio
fuente
2
.net 2.0 agregó genéricos.
Robert C. Barth
Esta es la única comprobación en tiempo de compilación en este hilo, gracias.
Dustin Malone
2

Lo que funcionó para mí es:

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

Dutchman078
fuente
1

Recientemente intenté usar la respuesta de Andrew Kennan y no me funcionó por alguna razón. Utilicé esto en su lugar y funcionó (nota: podría ser necesario escribir el espacio de nombres).

if (typeof(someObject).GetInterface("MyNamespace.IMyInterface") != null)
jahu
fuente
2
Si terminas yendo por esta ruta, no soy un fanático de las cadenas mágicas, así que como mínimo cambiaría esto para que sea typeof (IMyInterface) .Name en lugar de "MyNamespace.IMyInterface". Ayuda a nombrar la prueba de refactorización como un bono.
greyalien007
0

solía

Assert.IsTrue(myObject is ImyInterface);

para una prueba en mi unidad de prueba que prueba que myObject es un objeto que ha implementado mi interfaz ImyInterface.

iamrcw
fuente
-1

Tuve una situación en la que estaba pasando una variable a un método y no estaba seguro de si iba a ser una interfaz o un objeto.

Los objetivos fueron:

  1. Si item es una interfaz, cree una instancia de un objeto basado en esa interfaz con la interfaz como parámetro en la llamada del constructor.
  2. Si el artículo es un objeto, devuelve un valor nulo ya que el constructor de mis llamadas espera una interfaz y no quería que el código se acumulara.

Lo logré con lo siguiente:

    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
fuente
-12

Esto debería funcionar :

MyInstace.GetType().GetInterfaces();

Pero bueno también:

if (obj is IMyInterface)

O incluso (no muy elegante):

if (obj.GetType() == typeof(IMyInterface))
Yoann si
fuente
99
La comprobación de la igualdad de typeof (IMyInterface) siempre fallará. Voto negativo
Jay Bazuzi el
Derecha. No hay instancias de una interfaz.
Rauhotz el