Sprawdź, czy obiekt implementuje interfejs


Odpowiedzi:


569
if (object is IBlah)

lub

IBlah myTest = originalObject as IBlah

if (myTest != null)

85
+1 Drugi jest lepszy, ponieważ prawdopodobnie skończysz z koniecznością rzutu później z pierwszym, tym samym dając ci dwa rzuty („jest”, a następnie wyraźny rzut). Przy drugim podejściu rzucasz tylko raz.
Andrew Hare,

51
@Andrew: +1; Ponownie czas na link do klasycznego postu na blogu Double-Casting AntiPattern autorstwa Juliana M. Bucknalla .
Jeroen Wiert Pluimers

1
Optymalizacja prawdopodobnie nie sprawi, że rzucisz dwukrotnie w pierwszym przypadku?
BuZz

1
@Joreen, ten link pomija jeden punkt, jeśli pracujesz ze strukturą, której nie możesz użyć jako „ponieważ”, ponieważ nie będzie zawierał wartości zerowej, którą próbuje zwrócić „jak”, w takim przypadku musisz przejść przez zerowy klasa taka jak int ?, choć nie jest to problem, jeśli pracujesz tylko na poziomie interfejsu, ponieważ zawsze są to typy referencyjne
MikeT

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

224

Używanie operatorów islub asjest poprawnym sposobem, jeśli znasz typ interfejsu w czasie kompilacji i masz instancję testowanego typu. Coś, o czym nikt inny nie wspomniał, to Type.IsAssignableFrom:

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

Myślę, że jest to o wiele ładniejsze niż przeglądanie tablicy zwróconej przez GetInterfacesi ma tę zaletę, że działa również dla klas.


Próbuję ustalić, czy typ implementuje jakąś instancję IList. Używam „typeof (IList <>). IsAssignableFrom (someType)”, ale to nie działa.
KeyboardDrummer,

3
Być może lepiej zadać to w innym pytaniu. Jeśli someType jest typem elementów listy, możesz potrzebować typeof (IList <>). MakeGenericType (someType). Jeśli someType jest typem listy, powinieneś spojrzeć na Type.GetGenericArguments i Type.GetGenericTypeDefinition.
Andrew Kennan,

Używam tego do sprawdzania typu w systemie wtyczek. Można go użyć w sytuacjach, gdy instancja obiektu jeszcze nie istnieje. Ale używam zarówno tego stylu, jak i Roberta, w zależności od tego, co robię, więc głosowałem w obie strony.
James

To jest starszy komentarz, ale aby odpowiedzieć na pytanie @ Steenreem, użyj typeof(IList).IsAssignableFrom(someType), bez <>.
saluce

Ta metoda działa nawet z operatorami konwersji, a jeśli zaangażowane są konwertery Type
Harald Coppoolse,

22

Na przykład:

if (obj is IMyInterface) {}

Dla klasy:

Sprawdź, czy typeof(MyClass).GetInterfaces()zawiera interfejs.


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

2
lub: if (typeof (MyClass) .GetInterfaces (). Zawiera (typeof (IMyInterface))) {...}
Lance Fisher


16

Odmiana odpowiedzi @ AndrewKennan, której ostatnio użyłem do typów uzyskanych w czasie wykonywania:

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

7

Ten post jest dobrą odpowiedzią.

public interface IMyInterface {}

public class MyType : IMyInterface {}

To prosta próbka:

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

lub

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

3

Oprócz testowania za pomocą operatora „jest” możesz ozdobić swoje metody, aby upewnić się, że przekazywane do niego zmienne implementują określony interfejs, na przykład:

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

Nie jestem pewien, w której wersji .Net został zaimplementowany, więc może nie działać w twojej wersji.


2
.net 2.0 dodane ogólne.
Robert C. Barth

To jedyna kontrola czasu kompilacji w tym wątku, dzięki.
Dustin Malone

2

Dla mnie zadziałało:

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


1

Ostatnio próbowałem użyć odpowiedzi Andrew Kennana i z jakiegoś powodu nie działało to dla mnie. Użyłem tego zamiast tego i zadziałało (uwaga: może być wymagane wpisanie przestrzeni nazw).

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

2
Jeśli pójdziesz tą drogą, nie jestem fanem magicznych ciągów, więc przynajmniej zmienię to na typeof (IMyInterface) .Name zamiast „MyNamespace.IMyInterface”. Pomaga uczynić z niego dowód refaktoryzacji jako bonus.
greyalien007

0

użyłem

Assert.IsTrue(myObject is ImyInterface);

dla testu w moim teście jednostkowym, który sprawdza, czy myObject jest obiektem, który zaimplementował mój interfejs ImyInterface.


-1

Miałem sytuację, w której przekazywałem zmienną do metody i nie byłem pewien, czy będzie to interfejs, czy obiekt.

Cele były następujące:

  1. Jeśli item jest interfejsem, utwórz obiekt na podstawie tego interfejsu, przy czym interfejs jest parametrem w wywołaniu konstruktora.
  2. Jeśli element jest obiektem, zwróć wartość null, ponieważ konstruktor dla moich wywołań oczekuje interfejsu i nie chciałem, aby kod był tankowany.

Osiągnąłem to dzięki:

    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

To powinno działać:

MyInstace.GetType().GetInterfaces();

Ale też miłe:

if (obj is IMyInterface)

Lub nawet (niezbyt elegancko):

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

9
Sprawdzanie równości do typeof (IMyInterface) zawsze kończy się niepowodzeniem. Doceniony.
Jay Bazuzi

Dobrze. Brak instancji interfejsu.
Rauhotz
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.