Check if 'T' inherits or implements a class/interface

C#Generics

C# Problem Overview


Is there a way to test if T inherits/implements a class/interface?

private void MyGenericClass<T> ()
{
	if(T ... inherits or implements some class/interface
}

C# Solutions


Solution 1 - C#

There is a Method called Type.IsAssignableFrom().

To check if T inherits/implements Employee:

typeof(Employee).IsAssignableFrom(typeof(T));

If you are targeting .NET Core, the method has moved to TypeInfo:

typeof(Employee).GetTypeInfo().IsAssignableFrom(typeof(T).Ge‌​tTypeInfo())

Note that if you want to constrain your type T to implement some interface or inherit from some class, you should go for @snajahi's answer, which uses compile-time checks for that and genereally resembles a better approach to this problem.

Solution 2 - C#

You can use constraints on the class.

MyClass<T> where T : Employee

Take a look at http://msdn.microsoft.com/en-us/library/d5x73970.aspx

Solution 3 - C#

If you want to check during compilation: Error if if T does NOT implement the desired interface/class, you can use the following constraint

public void MyRestrictedMethod<T>() where T : MyInterface1, MyInterface2, MySuperClass
{
    //Code of my method here, clean without any check for type constraints.
}

I hope that helps.

Solution 4 - C#

The correct syntax is

typeof(Employee).IsAssignableFrom(typeof(T))

Documentation

>Return Value: true if c and the current Type represent the same type, or if the current Type is in the inheritance hierarchy of c, or if the current Type is an interface that c implements, or if c is a generic type parameter and the current Type represents one of the constraints of c, or if c represents a value type and the current Type represents Nullable<c> (Nullable(Of c) in Visual Basic). false if none of these conditions are true, or if c is null.

source

Explanation

If Employee IsAssignableFrom T then T inherits from Employee.

The usage

typeof(T).IsAssignableFrom(typeof(Employee)) 

returns true only when either

  1. T and Employee represent the same type; or,
  2. Employee inherits from T.

This may be intended usage in some case, but for the original question (and the more common usage), to determine when T inherits or implements some class/interface, use:

typeof(Employee).IsAssignableFrom(typeof(T))

Solution 5 - C#

What everyone really means is:

typeof(BaseType).IsAssignableFrom(typeof(DerivedType)) // => true

because you can literally assign from an instance of a DerivedType to an instance of a BaseType:

DerivedType childInstance = new DerivedType();
BaseType parentInstance = childInstance; // okay, assigning base from derived
childInstance = (DerivedType) parentInstance; // not okay, assigning derived from base

when

public class BaseType {}
public class DerivedType : BaseType {}

And some concrete examples if you're having trouble wrapping your head around it:

(via LinqPad, hence the HorizontalRun and Dump)

void Main()
{
	// http://stackoverflow.com/questions/10718364/check-if-t-inherits-or-implements-a-class-interface
	
	var b1 = new BaseClass1();
	
	var c1 = new ChildClass1();
	var c2 = new ChildClass2();
	var nb = new nobase();
	
	Util.HorizontalRun(
		"baseclass->baseclass,child1->baseclass,baseclass->child1,child2->baseclass,baseclass->child2,nobase->baseclass,baseclass->nobase",
		b1.IsAssignableFrom(typeof(BaseClass1)),
		c1.IsAssignableFrom(typeof(BaseClass1)),
		b1.IsAssignableFrom(typeof(ChildClass1)),
		c2.IsAssignableFrom(typeof(BaseClass1)),
		b1.IsAssignableFrom(typeof(ChildClass2)),
		nb.IsAssignableFrom(typeof(BaseClass1)),
		b1.IsAssignableFrom(typeof(nobase))
		).Dump("Results");
	
	var results = new List<string>();
	string test;
	
	test = "c1 = b1";
	try {
		c1 = (ChildClass1) b1;
		results.Add(test);
	} catch { results.Add("FAIL: " + test); }
	
	test = "b1 = c1";
	try {
		b1 = c1;
		results.Add(test);
	} catch { results.Add("FAIL: " + test); }
	
	test = "c2 = b1";
	try {
		c2 = (ChildClass2) b1;
		results.Add(test);
	} catch { results.Add("FAIL: " + test); }

	test = "b1 = c2";
	try {
		b1 = c2;
		results.Add(test);
	} catch { results.Add("FAIL: " + test); }
			
	results.Dump();
}

// Define other methods and classes here
public static class exts {
	public static bool IsAssignableFrom<T>(this T entity, Type baseType) {
		return typeof(T).IsAssignableFrom(baseType);
	}
}


class BaseClass1 {
	public int id;
}

class ChildClass1 : BaseClass1 {
	public string name;
}

class ChildClass2 : ChildClass1 {
	public string descr;
}

class nobase {
	public int id;
	public string name;
	public string descr;
}

Results

> baseclass->baseclass > > True > > > > child1->baseclass > > False > > > > baseclass->child1 > > True > > > > child2->baseclass > > False > > > > baseclass->child2 > > True > > > > nobase->baseclass > > False > > > > baseclass->nobase > > False

and

> * FAIL: c1 = b1 > * b1 = c1 > * FAIL: c2 = b1 > * b1 = c2

Solution 6 - C#

I believe syntax is: typeof(Employee).IsAssignableFrom(typeof(T));

Solution 7 - C#

Although IsAssignableFrom is the best way as others have stated, if you only need to check if a class inherits from another, typeof(T).BaseType == typeof(SomeClass) does the job too.

Solution 8 - C#

Alternate ways to tell if an object o inherits a class or implements an interface is to use the is and as operators.

If you want to only know if an object inherits a class or implements an interface, the is operator will return a boolean result:

bool isCompatibleType = (o is BaseType || o is IInterface);

If you want to use the inherited class or implemented interface after your test, the as operator will perform a safe cast, returning a reference to the inherited class or the implemented interface if compatible or null if not compatible:

BaseType b = o as BaseType; // Null if d does not inherit from BaseType.

IInterface i = o as IInterface; // Null if d does not implement IInterface.

If you have only the type T, then use @nikeee's answer.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser1229895View Question on Stackoverflow
Solution 1 - C#nikeeeView Answer on Stackoverflow
Solution 2 - C#Sachin KainthView Answer on Stackoverflow
Solution 3 - C#snajahiView Answer on Stackoverflow
Solution 4 - C#Luke WillisView Answer on Stackoverflow
Solution 5 - C#drzausView Answer on Stackoverflow
Solution 6 - C#ChalkyView Answer on Stackoverflow
Solution 7 - C#JedView Answer on Stackoverflow
Solution 8 - C#Suncat2000View Answer on Stackoverflow