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 )

JoshRivers
fonte

Respostas:

570
if (object is IBlah)

ou

IBlah myTest = originalObject as IBlah

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

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

Rauhotz
fonte
11
if (Array.IndexOf (typeof (MyClass) .GetInterfaces (), typeof (IMyInterface))! = -1) {...}
Constantin
2
ou: if (typeof (MyClass) .GetInterfaces (). Contém (typeof (IMyInterface))) {...}
Lance Fisher
17

Se você deseja usar o objeto de conversão de tipo após a verificação:
Desde o C # 7.0:

if (obj is IMyInterface myObj)

É o mesmo que

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

Consulte .NET Docs: correspondência de padrões com o ispadrão # Type

Martin Schneider
fonte
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
}
Famousgarkin
fonte
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))
eliasetm
fonte
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.

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

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

iamrcw
fonte
-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);
Anthony Tristan
fonte
-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))
Yoann. B
fonte
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