1

I have an open generic type definition and want to check whether this open definition implements an open interface definition.

interface IMyInterface<T>
{}
        
class GoodType<T> : IMyInterface<T>  where T : Enum
{
}

class BadType<T> where T : Enum
{
}

static bool IsOpenGenericTypeImplementing(Type candidate, Type iface) => 
    candidate.IsGenericTypeDefinition && 
    candidate.GetGenericArguments().Length == 1 && 
    candidate.MakeGenericType(typeof(object)).IsAssignableTo(iface.MakeGenericType(typeof(object)));  // does not work

[Fact]
void Test()
{
    Assert.True(IsOpenGenericTypeImplementing(typeof(GoodType<>), typeof(IMyInterface<>)));
    Assert.False(IsOpenGenericTypeImplementing(typeof(BadType<>), typeof(IMyInterface<>)));
}

The problem with the approach above is that is will fail because of the Enum type constraint (ArgumentException).

I found some similar questions but all seem to need a closed generic type definition (<T> instead of <>). E.g. Finding out if a type implements a generic interface

stb
  • 772
  • 5
  • 15
  • Does [this](https://stackoverflow.com/questions/5461295/using-isassignablefrom-with-open-generic-types) answer your question? (Note that that accepted answer is significantly more expensive than it needs to be, as it iterates the list of interfaces multiple times, once for each base type) – canton7 Dec 16 '20 at 11:32
  • `following test will fail (exception)` What exception? – mjwills Dec 16 '20 at 11:37
  • 2
    Did you intend for your `SomeType` to implement `IEnumerable` btw? At the moment there's a generic type constraint `where T : IEnumerable` – canton7 Dec 16 '20 at 11:39
  • @canton7 You're right, I'll fix the question. – stb Dec 16 '20 at 16:26
  • 1
    I updated the question to make things more clear, sorry for bad (initial) question code quality. @canton7: Yes, the answer in https://stackoverflow.com/questions/5461295/using-isassignablefrom-with-open-generic-types solves my problem. I'll try to understand why :-) and then try to mark this as duplicate. Thank you! – stb Dec 16 '20 at 16:32
  • Basically you're just after `typeof(GoodType<>).GetInterfaces.Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IMyInterface<>))`: loop through all of the generic type definition's interfaces, and see whether the generic type definition of any of those matches the type you're after – canton7 Dec 16 '20 at 16:41
  • Yes @canton7, I took the other answer https://stackoverflow.com/questions/5461295/using-isassignablefrom-with-open-generic-types and converted it to a similar one-line expression like yours (but including base classes): `public static bool IsOpenGenericTypeAssignableTo(this Type givenType, Type genericType) => (givenType.IsGenericType && givenType.GetGenericTypeDefinition() == genericType) || givenType.GetInterfaces().Any(it => it.IsGenericType && it.GetGenericTypeDefinition() == genericType) || givenType.BaseType?.IsOpenGenericTypeAssignableTo(genericType) == true;` Thanks everyone! – stb Dec 16 '20 at 19:52
  • Yeah, I don't like that code, as it does the `GetInterfaces()` for each base class, when that's completely unnecessary. Also `Append` and `Prepend` exist these days -- no need to roll your own `Cons` – canton7 Dec 16 '20 at 19:55

1 Answers1

-2

Add following to the static method:

candidate.GetInterfaces().Contains(typeof(IEnumerable))
zir
  • 119
  • 7
  • This, while technically correct for this particular scenario (and only because `IEnumerable` implements `IEnumerable`) doesn't cover the general case, which is what the OP is asking about – canton7 Dec 16 '20 at 13:28
  • @canton7: exactly. I will update my question and use an alternative interface to make this more clear. – stb Dec 16 '20 at 16:15