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

355

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

JoshRivers
источник

Ответы:

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()содержит ли интерфейс.

Rauhotz
источник
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
}
famousgarkin
источник
7

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

public interface IMyInterface {}

public class MyType : IMyInterface {}

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

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

или

typeof(MyType).GetInterfaces().Contains(typeof(IMyInterface))
eliasetm
источник
3

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

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

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

jamesmillerio
источник
2
.net 2.0 добавил дженерики.
Роберт С. Барт
Это единственный проверка во время компиляции в этой теме, спасибо.
Дастин Мэлоун
2

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

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

Dutchman078
источник
1

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

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

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

Assert.IsTrue(myObject is ImyInterface);

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

iamrcw
источник
-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.
Джей Базузи
Правильно. Там нет экземпляров интерфейса.
Раухотц