Teste se o objeto implementa interface


355

Qual é a maneira mais simples de testar se um objeto implementa uma determinada interface em C #? (Responda a esta pergunta em Java )

Respostas:


570
if (object is IBlah)

ou

IBlah myTest = originalObject as IBlah

if (myTest != null)

85
+1 O segundo é melhor, porque você provavelmente precisará lançar depois com o primeiro, dando a você dois lançamentos ("é" e depois um elenco explícito). Com a segunda abordagem, você lança apenas uma vez.
Andrew Hare

51
@ Andrew: +1; Mais uma vez, o link para o post clássico do blog Double-Casting AntiPattern de Julian M Bucknall .
Jeroen Wiert Pluimers 17/03/11

11
A otimização provavelmente não fará você transmitir duas vezes no primeiro caso?
21813 BuZz

11
@Joreen, esse link perde um ponto se você estiver trabalhando com uma estrutura que não pode usar "como" porque ele não conterá um nulo, que é o que o "as" tenta retornar; nesse caso, você precisa passar por um valor nulo classe como int ?, embora não um problema se o seu único trabalho ao nível da interface como eles estão sempre tipos de referência
miket

46
Desde C # 6.0:if (object is IBlah iblah) { iblah.SomeMethod(); }
Knelis 26/06

224

Usar os operadores isou asé a maneira correta se você souber o tipo de interface no momento da compilação e tiver uma instância do tipo que está testando. Algo que ninguém mais parece ter mencionado é Type.IsAssignableFrom:

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

Eu acho que isso é muito melhor do que olhar através da matriz retornada GetInterfacese tem a vantagem de trabalhar para as classes também.


Estou tentando determinar se um tipo implementa alguma instanciação do IList. Estou usando "typeof (IList <>). IsAssignableFrom (someType)" mas isso não está funcionando.
KeyboardDrummer

3
Talvez seja melhor fazer isso em outra pergunta. Se someType for o tipo dos elementos da lista, você poderá precisar typeof (IList <>). MakeGenericType (someType). Se someType for o tipo de lista, você deve procurar Type.GetGenericArguments e Type.GetGenericTypeDefinition.
Andrew Kennan

Eu uso isso para verificação de tipo em um sistema de plug-in. Pode ser usado em situações em que uma instância do objeto ainda não existe. Mas eu uso esse estilo e o de Robert, dependendo do que estou fazendo, e votei nos dois sentidos.
James

Este é um comentário antigo, mas para responder à pergunta de @ Steenreem, use typeof(IList).IsAssignableFrom(someType), sem o <>.
saluce

Este método também funciona com os operadores de conversão e se TypeConverters estão envolvidos
Harald Coppoolse

22

Para a instância:

if (obj is IMyInterface) {}

Para a turma:

Verifique se typeof(MyClass).GetInterfaces()contém a interface.


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

2
ou: if (typeof (MyClass) .GetInterfaces (). Contém (typeof (IMyInterface))) {...}
Lance Fisher


16

Uma variação na resposta de @ AndrewKennan que acabei usando recentemente para tipos obtidos em tempo de execução:

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

7

Este post é uma boa resposta.

public interface IMyInterface {}

public class MyType : IMyInterface {}

Este é um exemplo simples:

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

ou

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

3

Além de testar usando o operador "is", você pode decorar seus métodos para garantir que as variáveis ​​transmitidas a ele implementem uma interface específica, como:

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

Não tenho certeza em qual versão do .Net foi implementada, portanto, pode não funcionar na sua versão.


2
.net 2.0 adicionou genéricos.
Robert C. Barth

Esta é a única verificação em tempo de compilação neste segmento, obrigado.
Dustin Malone

2

O que funcionou para mim é:

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


1

Recentemente, tentei usar a resposta de Andrew Kennan e não funcionou para mim por algum motivo. Eu usei isso em vez disso e funcionou (nota: pode ser necessário escrever o espaço para nome).

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

2
Se você terminar esse caminho, eu não sou fã de seqüências de caracteres mágicas, portanto, eu alteraria no mínimo para ser typeof (IMyInterface) .Name em vez de "MyNamespace.IMyInterface". Ajuda a torná-lo um nome à prova de refatoração como um bônus.
Greyalien007

0

eu usei

Assert.IsTrue(myObject is ImyInterface);

para um teste no meu teste de unidade que testa que myObject é um objeto que implementou minha interface ImyInterface.


-1

Eu tive uma situação em que estava passando uma variável para um método e não tinha certeza se seria uma interface ou um objeto.

Os objetivos foram:

  1. Se item for uma interface, instancie um objeto com base nessa interface, sendo a interface um parâmetro na chamada do construtor.
  2. Se o item for um objeto, retorne um valor nulo, pois o construtor de minhas chamadas espera uma interface e eu não quero que o código seja armazenado.

Consegui isso com o seguinte:

    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

Isso deve funcionar:

MyInstace.GetType().GetInterfaces();

Mas legal também:

if (obj is IMyInterface)

Ou até (não muito elegante):

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

9
A verificação de igualdade para typeof (IMyInterface) sempre falha. Votado.
Jay Bazuzi

Direita. Não há instâncias de uma interface.
Rauhotz 4/01/09
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.