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.