This is a sweet piece of code, I have to say. The while loop implementation avoids the unnecessary recursion performance hit also. It's an elegant and beautiful solution to a meta-generic question.
–
EnocNRollJan 19 '09 at 18:26

2

I have added this method to my ReflectionUtils static class in my framework, and I have also adapted it as an extension method for object by defining toCheck within the method as Type toCheck = obj.GetType(); given "this object obj" is the first parameter.
–
EnocNRollJan 23 '09 at 22:22

9

The while loop will not break if the toCheck type is not a class (ie, interface). This will cause a NullReferenceException.
–
JD CourtoyDec 23 '09 at 21:54

1

This will also return true if toCheck is the generic type you are looking for.
–
oillioMay 5 '10 at 4:04

JaredPar's code answer is fantastic, but I have a tip that would make it unnecessary if your generic types are not based on value type parameters. I was hung up on why the "is" operator would not work, so I have also documented the results of my experimentation for future reference. Please enhance this answer to further enhance its clarity.

TIP:

If you make certain that your GenericClass implementation inherits from an abstract non-generic base class such as GenericClassBase, you could ask the same question without any trouble at all like this:

typeof(Test).IsSubclassOf(typeof(GenericClassBase))

IsSubclassOf()

My testing indicates that IsSubclassOf() does not work on parameterless generic types such as

typeof(GenericClass<>)

whereas it will work with

typeof(GenericClass<SomeType>)

Therefore the following code will work for any derivation of GenericClass<>, assuming you are willing to test based on SomeType:

typeof(Test).IsSubclassOf(typeof(GenericClass<SomeType>))

The only time I can imagine that you would want to test by GenericClass<> is in a plug-in framework scenario.

Thoughts on the "is" operator

At design-time C# does not allow the use of parameterless generics because they are essentially not a complete CLR type at that point. Therefore, you must declare generic variables with parameters, and that is why the "is" operator is so powerful for working with objects. Incidentally, the "is" operator also can not evaluate parameterless generic types.

The "is" operator will test the entire inheritance chain, including interfaces.

So, given an instance of any object, the following method will do the trick:

bool IsTypeof<T>(object t)
{
return (t is T);
}

This is sort of redundant, but I figured I would go ahead and visualize it for everybody.

This was the answer I was looking for! Works for concrete types AND for interfaces, thanks :-)
–
Menno SquaredSep 3 '12 at 11:21

2

I'm a puzzled about the ResolveGenericTypeDefinition method. The "shouldUseGenericType" variable is really assigned the value: !parent.IsGenericType || parent.GetGenericTypeDefinition() == parent; So you replace that variable with the expansion of the if statement: if (parent.IsGenericType && shouldUseGenericType) and you get if (parent.IsGenericType && (!parent.IsGenericType || parent.GetGenericTypeDefinition() == parent)) which then reduces to if (parent.IsGenericType && parent.GetGenericTypeDefinition() == parent)) parent = parent.GetGenericTypeDefinition();
–
Michael BlackburnDec 4 '12 at 23:17

2

Which would seem to do nothing. If these were value types that would be akin to int j = 0;if (j is an int && j == 0){ j=0; } Am I getting my reference equals and value equals mixed up? I thought there was only one instance of each Type in memory, so two variables that point to the same type are in fact pointing to the same location in memory.
–
Michael BlackburnDec 4 '12 at 23:20

2

if its already the same as the parent, just return it! and he's calling GetGenericTypeDef too many times. It just needs to be called once
–
AaronHSFeb 19 '13 at 9:16

1

Sorry, I will add a new comment below.
–
Menno SquaredMar 12 '13 at 11:48

It might be overkill but I use extension methods like the following. They check interfaces as well as subclasses. It can also return the type that has the specified generic definition.

E.g. for the example in the question it can test against generic interface as well as generic class. The returned type can be used with GetGenericArguments to determine that the generic argument type is "SomeType".

This is the only solution that worked for me. I couldn't find any other solutions that worked with classes that have multiple type parameters. Thank you.
–
HotenJan 3 at 4:24

1

I really appreciated your posting all of these test cases. I do think that cases 68 and 69 should be false instead of true, as you have ClassB, ClassA on the left and ClassA, ClassB on the right.
–
GraxJan 7 at 22:58

You're right, @Grax. I do not have time to make the correction now, but I will update my post as soon as it's done. I think the correction must be in "VerifyGenericArguments" method
–
Xav987Feb 3 at 16:37

@Grax : I found some time to make the correction. I added the ClassB2 class, I changed VerifyGenericArguments, and I added a control at the call of VerifyGenericArguments. I also modified the cases 68 and 69, and added 68-2, 68-3, 68-4, 69-2, 69-3 and 69-4.
–
Xav987Mar 16 at 16:24

JaredPar's solution indeed works for typeof(type<>) as toCheck. Also you really need the null check as in JaredPar's solution. Furthermore, I do not know what else you're achieving by replacing cur == generic in his solution by cur.IsGenericType && generic.GetGenericTypeDefinition() == cur.GetGenericTypeDefinition() other than restricting your method to work only for generic types. In other words, anything like this fails with an exception: IsSubclassOfRawGeneric(typeof(MyClass), typeof(MyClass<>))
–
nawfalMay 9 '13 at 17:22

Good addition. Gave both you and jaredpar an upvote. My only comment is you reversed the position of the types(from jaredpar's answer) because of the extension method. I removed it as an extension method and it threw me off for a bit. Not your problem but mine. Just wanted to give the next person heads up. Thanks again.
–
TonyJun 18 at 17:02