Verifica se l'oggetto implementa l'interfaccia


355

Qual è il modo più semplice di testare se un oggetto implementa una determinata interfaccia in C #? (Rispondi a questa domanda in Java )

Risposte:


570
if (object is IBlah)

o

IBlah myTest = originalObject as IBlah

if (myTest != null)

85
+1 Il secondo è migliore perché probabilmente finirai per aver bisogno di lanciare in seguito con il primo dando così due cast ("is" e quindi un cast esplicito). Con il secondo approccio lanci solo una volta.
Andrew Hare,

51
@Andrew: +1; Di nuovo tempo per il link al classico post sul blog Double-Casting AntiPattern di Julian M Bucknall .
Jeroen Wiert Pluimers,

1
L'ottimizzazione probabilmente non ti sarà lanciata due volte nel primo caso?
BuZz,

1
@Joreen, quel collegamento manca un punto se stai lavorando con una struttura che non puoi usare "as" perché non conterrà un valore nullo che è ciò che "as" cerca di restituire, in tal caso devi passare attraverso un nullable class like int ?, anche se non è un problema se lavori solo a livello di interfaccia in quanto sono sempre tipi di riferimento
MikeT

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

224

L'uso degli operatori iso asè il modo corretto se si conosce il tipo di interfaccia in fase di compilazione e si dispone di un'istanza del tipo che si sta testando. Qualcosa che nessun altro sembra aver menzionato è Type.IsAssignableFrom:

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

Penso che sia molto più semplice che guardare attraverso l'array restituito GetInterfacese ha il vantaggio di lavorare anche per le classi.


Sto cercando di determinare se un tipo implementa un'istanza di IList. Sto usando "typeof (IList <>). IsAssignableFrom (someType)" ma non funziona.
KeyboardDrummer,

3
Potrebbe essere meglio chiedere questo in un'altra domanda. Se someType è il tipo di elementi dell'elenco, potrebbe essere necessario typeof (IList <>). MakeGenericType (someType). Se someType è il tipo di elenco, dovresti guardare Type.GetGenericArguments e Type.GetGenericTypeDefinition.
Andrew Kennan,

Lo uso per il controllo del tipo in un sistema di plugin. Può essere utilizzato in situazioni in cui non esiste ancora un'istanza dell'oggetto. Ma uso sia questo stile sia quello di Robert a seconda di quello che sto facendo, quindi ho votato in entrambi i modi.
James,

Questo è un commento più vecchio, ma per rispondere alla domanda di @ Steenreem, usa typeof(IList).IsAssignableFrom(someType), senza il <>.
salse

Questo metodo funziona anche con operatori di conversione e se sono coinvolti
TypeConverters

22

Per esempio:

if (obj is IMyInterface) {}

Per la classe:

Controlla se typeof(MyClass).GetInterfaces()contiene l'interfaccia.


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

2
oppure: if (typeof (MyClass) .GetInterfaces (). Contiene (typeof (IMyInterface))) {...}
Lance Fisher


16

Una variazione sulla risposta di @ AndrewKennan ho finito per usare di recente per i tipi ottenuti in fase di esecuzione:

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

7

Questo post è una buona risposta.

public interface IMyInterface {}

public class MyType : IMyInterface {}

Questo è un semplice esempio:

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

o

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

3

Oltre al test con l'operatore "is", puoi decorare i tuoi metodi per assicurarti che le variabili passate ad esso implementino una particolare interfaccia, in questo modo:

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

Non sono sicuro in quale versione di .Net sia stata implementata, quindi potrebbe non funzionare nella tua versione.


2
.net 2.0 ha aggiunto generici.
Robert C. Barth,

Questo è l' unico controllo in fase di compilazione in questo thread, grazie.
Dustin Malone,

2

Ciò che ha funzionato per me è:

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


1

Di recente ho provato a utilizzare la risposta di Andrew Kennan e per qualche motivo non ha funzionato per me. Ho usato questo invece e ha funzionato (nota: potrebbe essere necessario scrivere lo spazio dei nomi).

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

2
Se finisci per seguire questa strada, non sono un fan delle stringhe magiche, quindi cambierei almeno questo in typeof (IMyInterface) .Name invece di "MyNamespace.IMyInterface". Aiuta a nominarlo prova di refactoring come bonus.
greyalien007,

0

ero solito

Assert.IsTrue(myObject is ImyInterface);

per un test nel mio unit test che verifica che myObject sia un oggetto che ha implementato la mia interfaccia ImyInterface.


-1

Ho avuto una situazione in cui stavo passando una variabile a un metodo e non ero sicuro che sarebbe stata un'interfaccia o un oggetto.

Gli obiettivi erano:

  1. Se l'elemento è un'interfaccia, creare un'istanza di un oggetto in base a tale interfaccia con l'interfaccia come parametro nella chiamata del costruttore.
  2. Se l'articolo è un oggetto, restituire un valore null poiché il constuctor per le mie chiamate si aspetta un'interfaccia e non volevo che il codice si accumulasse.

Ho raggiunto questo con il seguente:

    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

Questo dovrebbe funzionare:

MyInstace.GetType().GetInterfaces();

Ma anche bello:

if (obj is IMyInterface)

O anche (non molto elegante):

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

9
Il controllo dell'uguaglianza con typeof (IMyInterface) fallirà sempre. Downvoted.
Jay Bazuzi,

Giusto. Non ci sono istanze di un'interfaccia.
Rauhotz,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.