706

Does reflection in C# offer a way to determine if some given System.Type type models some interface?

public interface IMyInterface {}

public class MyType : IMyInterface {}

// should yield 'true'
typeof(MyType)./* ????? */MODELS_INTERFACE(IMyInterface);
Xavier Poinas
  • 19,377
  • 14
  • 63
  • 95
Yippie-Ki-Yay
  • 22,026
  • 26
  • 90
  • 148

16 Answers16

1222

You have a few choices:

  1. typeof(IMyInterface).IsAssignableFrom(typeof(MyType))
  2. typeof(MyType).GetInterfaces().Contains(typeof(IMyInterface))
  3. With C# 6 you can use typeof(MyType).GetInterface(nameof(IMyInterface)) != null

For a generic interface, it’s a bit different.

typeof(MyType).GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IMyInterface<>))
FlyingFoX
  • 3,379
  • 3
  • 32
  • 49
Jeff
  • 35,755
  • 15
  • 108
  • 220
  • 84
    Remember that typeof(IMyInterface).IsAssignableFrom(typeof(IMyInterface)) is also true, which may have an unexpected result on your code. – Chris Kemp Aug 23 '12 at 12:40
  • 34
    It sure was easy to not pay attention and get the arguments for `IsAssignableFrom` backwards. I will go with `GetInterfaces` now :p – Benjamin Apr 10 '13 at 22:21
  • 18
    The `IsAssignableFrom(t1)` variant is about 3x faster than the `GetInterfaces().Contains(t2)` counterpart in my code. – Pierre Arnaud May 15 '13 at 04:36
  • 12
    You can also use `typeof(MyType).GetInterface("IMyInterface") != null` – Kosta Aug 01 '13 at 13:53
  • 33
    @PierreArnaud: IsAssignableFrom does eventually calls GetInterfaces, so probably your test checked the GetInterfaces first and IsAssignable after. That is because GetInterfaces caches it's results so the first invocation costs more – Panos Theof Oct 11 '13 at 11:23
  • 1
    My performance test of `IsAssignableFrom` was done by repeatedly calling it with the same arguments. So yes, any caching done by this method would produce significant speed ups. – Pierre Arnaud Oct 29 '13 at 05:33
  • 5
    as of the writing of this comment, your at 404, here a +1 so you can be found again – Rémi Dec 14 '15 at 14:44
  • 24
    A small change to @Kosta's answer. With C# 6 we can do `typeof(MyType).GetInterface(nameof(IMyInterface)) != null` for better type safety and refactoring. – aholmes Mar 09 '16 at 03:57
  • Still holds the risk of multiple interfaces with the same name. – Sellorio Nov 06 '17 at 03:53
  • 4
    Did some tests and it appears that `IsAssignableFrom` is 6x faster than `GetInterfaces().Contains`. On a side note, `GetInterfaces` is cached but `IsAssignableFrom` is not. Even with the caching `GetInterfaces().Contains` is 3.5x slower than `IsAssignableFrom`. – Sellorio Nov 06 '17 at 04:17
  • 6
    One more note, IsAssignableFrom returns true only if the interface is "directly" implemented by the type: i.e. `interface A{} interface B:A{} class C:B{}` `typeof(C).IsAssignableFrom(typeof(A))` returns `false` while `typeof(C).GetInterfaces().Contains(typeof(A))` or `typeof(C).GetInterface(nameof(A)) != null` are both true – adospace Mar 07 '19 at 09:37
  • 4
    @adospace It should be `typeof(IMyInterface).IsAssignableFrom(typeof(MyType))` if you want to test if MyType implements IMyInterface. To help remember the correct order: `// If you can do this... if (typeof(IMyInterface).IsAssignableFrom(typeof(MyType)) { // then you can do this... IMyInterface obj = new MyType(); }` – Suncat2000 Oct 09 '20 at 11:59
  • @aholmes nameof only returns a partial type name, so if you have more than one interface with the same short name, you might get unexpected results. For a real world example, I have multiple versions of IService in various projects in a large solution. – John Zabroski Feb 09 '23 at 15:36
107

Use Type.IsAssignableFrom:

typeof(IMyInterface).IsAssignableFrom(typeof(MyType));
Snea
  • 1,867
  • 2
  • 14
  • 21
36
typeof(IMyInterface).IsAssignableFrom(someclass.GetType());

or

typeof(IMyInterface).IsAssignableFrom(typeof(MyType));
ajma
  • 12,106
  • 12
  • 71
  • 90
  • 46
    If you already have an instance of the class a much better approach is simply `someclass is IMyInterface` as that doesn't involve the cost of reflection at all. So, while not wrong, its not an ideal way to do it. – Arrya Regan Jul 27 '12 at 20:17
  • 2
    @James - Agree. Even Resharper gives the same suggestion. – Angshuman Agarwal Jun 11 '13 at 09:24
  • @JamesJ.ReganIV you should post that as an answer, I almost missed your comment – reggaeguitar Nov 03 '14 at 21:29
  • 1
    @reggaeguitar, thanks, but the comment doesn't answer the original question. The question asks for the Reflection solution, I am just saying in this answer's first case where you do have an instance of the object reflection isn't the ideal solution. – Arrya Regan Nov 03 '14 at 21:40
  • 1
    @JamesJ.ReganIV Actually, `is` checks in both directions of the inheritance hierarchy whereas `IsAssignableFrom` only checks upwards. Also, if you have an instance of an object, you should call `IsInstanceOfType` (which also only looks upwards). – Sellorio Nov 06 '17 at 03:57
  • @MrUniverse `is` only checks in one direction, or else `new object() is string` would be true. – Jon Hanna Dec 28 '17 at 12:14
  • @JonHanna That's not exactly what I meant but I think I was confused. – Sellorio Jan 02 '18 at 07:54
24

Use Type.IsAssignableTo (as of .NET 5.0):

typeof(MyType).IsAssignableTo(typeof(IMyInterface));

As stated in a couple of comments IsAssignableFrom may be considered confusing by being "backwards".

olabacker
  • 1,232
  • 1
  • 16
  • 27
15
public static bool ImplementsInterface(this Type type, Type ifaceType) 
{
    Type[] intf = type.GetInterfaces();
    for(int i = 0; i < intf.Length; i++) 
    {
        if(intf[ i ] == ifaceType) 
        {
            return true;
        }
    }
    return false;
}

I think this is the correct release, for three reasons:

  1. It uses GetInterfaces and not IsAssignableFrom, it's faster since IsAssignableFrom eventually after several checks does call GetInterfaces.
  2. It iterates over the local array, so there will be no bounds checks.
  3. It uses the == operator which is defined for Type, so probably is safer than the Equals method (that the Contains call, will eventually use).
Emond
  • 50,210
  • 11
  • 84
  • 115
Panos Theof
  • 1,450
  • 1
  • 21
  • 27
  • 10
    +1 for content, I hate the spaces around the parens and the Egyptian braces though. Also the whole method can be written as: return type.GetInterfaces().Any(t => t == ifaceType); – reggaeguitar Nov 03 '14 at 19:49
  • 1
    Type.IsAssignableFrom() internaly acts exactly like your code – gdbdable Dec 15 '14 at 13:27
  • 1
    Also why not type.GetInterfaces().Contains(ifaceType) which doesnt use LINQ. –  Oct 30 '16 at 02:48
12

If you have a type or an instance you can easily check if they support a specific interface.

To test if an object implements a certain interface:

if(myObject is IMyInterface) {
  // object myObject implements IMyInterface
}

To test if a type implements a certain interface:

if(typeof(IMyInterface).IsAssignableFrom(typeof(MyType))) {
  // type MyType implements IMyInterface
}

If you got a generic object and want to do a cast as well as a check if the interface you cast to is implemented the code is:

 var myCastedObject = myObject as IMyInterface;

    if(myCastedObject != null) {
      // object myObject implements IMyInterface
    }
10

I just did:

public static bool Implements<I>(this Type source) where I : class
{
  return typeof(I).IsAssignableFrom(source);
}

I wish I could have said where I : interface, but interface is not a generic parameter constraint option. class is as close as it gets.

Usage:

if(MyType.Implements<IInitializable>())
  MyCollection.Initialize();

I just said Implements because that's more intuitive. I always get IsAssignableFrom flip-flopped.

toddmo
  • 20,682
  • 14
  • 97
  • 107
  • You could do `return typeof(I).IsInterface && typeof(I).IsAssignableFrom(source);` to return false on any 'incorrect' usages of the method, that is; using it with a class type instead of an interface type, alternatively throw an exception if the type-parameter is not an interface. Though you could argue that a derived class 'implements' it's parent... – Sindri Jóelsson Oct 17 '18 at 15:36
8

As someone else already mentioned: Benjamin Apr 10 '13 at 22:21"

It sure was easy to not pay attention and get the arguments for IsAssignableFrom backwards. I will go with GetInterfaces now :p –

Well, another way around is just to create a short extension method that fulfills, to some extent, the "most usual" way of thinking (and agreed this is a very little personal choice to make it slightly "more natural" based on one's preferences):

public static class TypeExtensions
{
    public static bool IsAssignableTo(this Type type, Type assignableType)
    {
        return assignableType.IsAssignableFrom(type);
    }
}

And why not going a bit more generic (well not sure if it is really that interesting, well I assume I'm just passing another pinch of 'syntaxing' sugar):

public static class TypeExtensions
{
    public static bool IsAssignableTo(this Type type, Type assignableType)
    {
        return assignableType.IsAssignableFrom(type);
    }

    public static bool IsAssignableTo<TAssignable>(this Type type)
    {
        return IsAssignableTo(type, typeof(TAssignable));
    }
}

I think it might be much more natural that way, but once again just a matter of very personal opinions:

var isTrue = michelleType.IsAssignableTo<IMaBelle>();
Natalie Perret
  • 8,013
  • 12
  • 66
  • 129
  • 4
    Is there a reason you didn't just put the implementation directly in the extension method? I mean sure this lets you call it both ways, but why would you ever need to do that? – Mark A. Donohoe Jan 24 '17 at 16:53
  • @MarqueIV sorry to get back to you almost 2 years late, well I guess it was an old bad habit back then to wrap helper method in extension method to avoid repeating code, will edit my answer :) – Natalie Perret Dec 22 '18 at 23:31
  • 1
    @MarqueIV done plus changed my other bad habit of not using alias , i.e. `Boolean` => `bool` (I don't why I used to have some strict "fancy" rules of coding when I was younger). – Natalie Perret Dec 22 '18 at 23:57
7

Modifying Jeff's answer for optimal performance (thanks to performance test by Pierre Arnaud):

var type = typeof(MyType);
var implementsInterface = typeof(IMyInterface).IsAssignableFrom(type) && type.IsClass;

To find all types that implement an interface in a given Assembly:

var implementations = typeof(TypeInTargetAssembly).Assembly.GetTypes()
                          .Where(t => typeof(IMyInterface).IsAssignableFrom(t) && t.IsClass);
Ben Wilde
  • 5,552
  • 2
  • 39
  • 36
6

Anyone searching for this might find the following extension method useful:

public static class TypeExtensions
{
    public static bool ImplementsInterface(this Type type, Type @interface)
    {
        if (type == null)
        {
            throw new ArgumentNullException(nameof(type));
        }

        if (@interface == null)
        {
            throw new ArgumentNullException(nameof(@interface));
        }

        var interfaces = type.GetInterfaces();
        if (@interface.IsGenericTypeDefinition)
        {
            foreach (var item in interfaces)
            {
                if (item.IsConstructedGenericType && item.GetGenericTypeDefinition() == @interface)
                {
                    return true;
                }
            }
        }
        else
        {
            foreach (var item in interfaces)
            {
                if (item == @interface)
                {
                    return true;
                }
            }
        }

        return false;
    }
}

xunit tests:

public class TypeExtensionTests
{
    [Theory]
    [InlineData(typeof(string), typeof(IList<int>), false)]
    [InlineData(typeof(List<>), typeof(IList<int>), false)]
    [InlineData(typeof(List<>), typeof(IList<>), true)]
    [InlineData(typeof(List<int>), typeof(IList<>), true)]
    [InlineData(typeof(List<int>), typeof(IList<int>), true)]
    [InlineData(typeof(List<int>), typeof(IList<string>), false)]
    public void ValidateTypeImplementsInterface(Type type, Type @interface, bool expect)
    {
        var output = type.ImplementsInterface(@interface);
        Assert.Equal(expect, output);
    }
}
Bill Barry
  • 3,423
  • 2
  • 24
  • 22
5

Note that if you have a generic interface IMyInterface<T> then this will always return false:

  typeof(IMyInterface<>).IsAssignableFrom(typeof(MyType)) /* ALWAYS FALSE */

This doesn't work either:

  typeof(MyType).GetInterfaces().Contains(typeof(IMyInterface<>))  /* ALWAYS FALSE */

However, if MyType implements IMyInterface<MyType> this works and returns true:

  typeof(IMyInterface<MyType>).IsAssignableFrom(typeof(MyType))

However, you likely will not know the type parameter T at runtime. A somewhat hacky solution is:

  typeof(MyType).GetInterfaces()
                .Any(x=>x.Name == typeof(IMyInterface<>).Name)

Jeff's solution is a bit less hacky:

  typeof(MyType).GetInterfaces()
         .Any(i => i.IsGenericType 
             && i.GetGenericTypeDefinition() == typeof(IMyInterface<>));

Here's a extension method on Type that works for any case:

public static class TypeExtensions
{
    public static bool IsImplementing(this Type type, Type someInterface)
    {
        return type.GetInterfaces()
             .Any(i => i == someInterface 
                 || i.IsGenericType 
                    && i.GetGenericTypeDefinition() == someInterface);
    }
}

(Note that the above uses linq, which is probably slower than a loop.)

You can then do:

   typeof(MyType).IsImplementing(IMyInterface<>)
Diego
  • 18,035
  • 5
  • 62
  • 66
2

IsAssignableFrom is now moved to TypeInfo:

typeof(ISMSRequest).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo());
NucS
  • 619
  • 8
  • 21
codeputer
  • 1,987
  • 3
  • 19
  • 45
1

A correct answer is

typeof(MyType).GetInterface(nameof(IMyInterface)) != null;

However,

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

might return a wrong result, as the following code shows with string and IConvertible:

    static void TestIConvertible()
    {
        string test = "test";
        Type stringType = typeof(string); // or test.GetType();

        bool isConvertibleDirect = test is IConvertible;
        bool isConvertibleTypeAssignable = stringType.IsAssignableFrom(typeof(IConvertible));
        bool isConvertibleHasInterface = stringType.GetInterface(nameof(IConvertible)) != null;

        Console.WriteLine($"isConvertibleDirect: {isConvertibleDirect}");
        Console.WriteLine($"isConvertibleTypeAssignable: {isConvertibleTypeAssignable}");
        Console.WriteLine($"isConvertibleHasInterface: {isConvertibleHasInterface}");
    }

Results:

 isConvertibleDirect: True
 isConvertibleTypeAssignable: False
 isConvertibleHasInterface: True
EricBDev
  • 1,279
  • 13
  • 21
  • 5
    As you can see in accepted answer, you interchanged the types in usage of `IsAssignableFrom`. Just like Benjamin and Ehouarn warn about. – VV5198722 Jan 05 '18 at 16:37
0

what about

if(MyType as IMyInterface != null)

?

Pingi
  • 342
  • 3
  • 11
  • 7
    This is obvious when I have an instance. Not useful when I have a Type from reflection – edc65 Mar 02 '16 at 15:57
0

What about

typeof(IWhatever).GetTypeInfo().IsInterface
LaWi
  • 71
  • 1
  • 1
  • 6
-1

If you don't need to use reflection and you have an object, you can use this:

if(myObject is IMyInterface )
{
 // it's implementing IMyInterface
}
sskiba
  • 7
  • 1
  • 1
    Your solution will only work for existing objects. It is not applicable for types. Moreover, if you have a created object, you can get its type and perform the necessary checks. – Maxim Sep 22 '21 at 07:38