Проверьте, реализует ли объект интерфейс


355

Какой самый простой способ проверки, если объект реализует данный интерфейс в C #? (Ответ на этот вопрос на Java )

Ответы:


570
if (object is IBlah)

или

IBlah myTest = originalObject as IBlah

if (myTest != null)

85
+1 Второй лучше, потому что вам, вероятно, понадобится потом разыграть первого, что даст вам два приведения («есть» и затем явное приведение). При втором подходе вы разыгрываете только один раз.
— Эндрю Хэйр

51
@ Андрей: +1; Еще раз за ссылку на классическое сообщение в блоге Double-Casting AntiPattern от Джулиана М. Бакнолла .
— Йерун Wiert Pluimers

1
Оптимизация, вероятно, не заставит вас сыграть дважды в первом случае?
— BuZz

1
@Joreen, эта ссылка пропускает одно очко, если вы работаете со структурой, которую вы не можете использовать «как», потому что она не будет содержать ноль, то есть то, что пытается вернуть «как», в этом случае вы должны пройти через Nullable класс вроде int ?, хотя это не проблема, если вы работаете только на уровне интерфейса, так как они всегда являются ссылочными типами
— MikeT

46
Начиная с C # 6.0:if (object is IBlah iblah) { iblah.SomeMethod(); }
— Кнелис

224

Использование операторов isor asявляется правильным способом, если вы знаете тип интерфейса во время компиляции и имеете экземпляр типа, который вы тестируете. То, что никто, кажется, еще не упомянул, это Type.IsAssignableFrom:

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

Я думаю, что это гораздо лучше, чем просматривать массив, возвращенный GetInterfaces и имеет преимущество работы с классами.


Я пытаюсь определить, реализует ли тип некоторую реализацию IList. Я использую "typeof (IList <>). IsAssignableFrom (someType)", но это не работает.
— Клавишный

3
Возможно, вам лучше задать это в другом вопросе. Если someType является типом элементов списка, вам может понадобиться typeof (IList <>). MakeGenericType (someType). Если someType является типом списка, вы должны взглянуть на Type.GetGenericArguments и Type.GetGenericTypeDefinition.
— Эндрю Кеннан

Я использую это для проверки типов в системе плагинов. Его можно использовать в ситуациях, когда экземпляр объекта еще не существует. Но я использую и этот стиль, и стиль Роберта, в зависимости от того, что я делаю, поэтому я проголосовал в обе стороны.
— Джеймс

Это старый комментарий, но чтобы ответить на вопрос @ Steenreem, используйте typeof(IList).IsAssignableFrom(someType)без <>.
— приветствие

Этот метод работает даже с операторами преобразования, и если задействованы
— TypeConverters

22

Для примера:

if (obj is IMyInterface) {}

Для класса:

Проверьте, typeof(MyClass).GetInterfaces()содержит ли интерфейс.


1
if (Array.IndexOf (typeof (MyClass) .GetInterfaces (), typeof (IMyInterface))! = -1) {...}
— Константин

2
или: if (typeof (MyClass) .GetInterfaces (). Contains (typeof (IMyInterface))) {...}
— Лэнс Фишер


16

Вариант ответа @ AndrewKennan, который я недавно использовал для типов, полученных во время выполнения:

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

7

Этот пост является хорошим ответом.

public interface IMyInterface {}

public class MyType : IMyInterface {}

Это простой пример:

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

или

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

3

В дополнение к тестированию с использованием оператора «is» вы можете декорировать ваши методы, чтобы убедиться, что передаваемые ему переменные реализуют определенный интерфейс, например так:

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

Я не уверен, в какой версии .Net это было реализовано, поэтому он может не работать в вашей версии.


2
.net 2.0 добавил дженерики.
— Роберт С. Барт

Это единственный проверка во время компиляции в этой теме, спасибо.
— Дастин Мэлоун

2

Что сработало для меня:

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


1

Недавно я попытался использовать ответ Эндрю Кеннана, и он почему-то не сработал. Я использовал это вместо этого, и это сработало (примечание: может потребоваться запись пространства имен).

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

2
Если вы в конечном итоге идете по этому маршруту, я не фанат волшебных строк, поэтому я бы как минимум изменил это на typeof (IMyInterface) .Name вместо «MyNamespace.IMyInterface». Помогает сделать это название рефакторинг доказательства в качестве бонуса.
— greyalien007

0

я использовал

Assert.IsTrue(myObject is ImyInterface);

для теста в моем модульном тесте, который проверяет, что myObject является объектом, который реализовал мой интерфейс ImyInterface.


-1

У меня была ситуация, когда я передавал переменную методу и не был уверен, будет ли это интерфейс или объект.

Цели были:

  1. Если item является интерфейсом, создайте экземпляр объекта на основе этого интерфейса, причем интерфейс является параметром в вызове конструктора.
  2. Если элемент является объектом, вернуть ноль, так как конструктор для моих вызовов ожидает интерфейс, и я не хотел, чтобы код работал.

Я достиг этого с помощью следующего:

    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

Это должно работать:

MyInstace.GetType().GetInterfaces();

Но тоже приятно:

if (obj is IMyInterface)

Или даже (не очень элегантно):

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

9
Проверка на равенство typeof (IMyInterface) всегда будет неудачной. Downvoted.
— Джей Базузи

Правильно. Там нет экземпляров интерфейса.
— Раухотц
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.