Monday, March 08, 2010

How to tell if a type is a delegate

If you are holding a reference to a type, how can you tell if it’s a delegate? I expected there to be an ‘IsDelegate’ property on Type, but it isn’t there. The way I’ve found to do it, is to test if the type’s BaseType property inherits from System.MulticastDelegate.

public bool IsDelegate(Type type)
{
    return typeof (MulticastDelegate).IsAssignableFrom(type.BaseType);
}

Now this code:

Console.WriteLine("string    {0}", IsDelegate(typeof(string)));
Console.WriteLine("int       {0}", IsDelegate(typeof(int)));
Console.WriteLine("Func<int> {0}", IsDelegate(typeof(Func<int>)));
Console.WriteLine("Test      {0}", IsDelegate(typeof(Test)));

Will output this:

string    False
int       False
Func<int> True
Test      True

Do you know a better way?

Update: ‘Test’ in the example is defined like this:

public delegate int Test(int a, int b);

Thanks @Daneel3001 :)

10 comments:

Bruce Boughton said...

Delegates don't really get any special treatment in the System.Reflection world -- it just sees them as types like any other types. There's no obvious way to find out the delegate signature either--I suspect you'd need to get the "Invoke" method and interrogate its signature.

All of which is fine, just not obvious.

Asad ALi Butt said...

Do appreciate. just curious about why are you not using Delagate class instead of MulticastDelegate ? It returns the same result and probably we are interested in checking, if it is Type of "Delegate".


like as follows:

return typeof(Delegate).IsAssignableFrom(type.BaseType);

Mike Hadlow said...

@Bruce - yes, delegates are definately the poor relation when it comes to reflection. Thanks for the invoke tip, that was going to be my next topic.

@Asad - you are probably right. I just chose MulticastDelegate because that what the BaseType property was when I was inspecting delegates with the debugger. But yes, MulticastDelegate inherits from Delegate so Delegate would probably be the better choice. Thanks for pointing it out.

Richard OD said...

Actually Mike, you might of made the right choice. Brad Abrams advice is to pretend only Multicast Delegate exists- http://blogs.msdn.com/brada/archive/2004/02/05/68415.aspx.

At the end of the day there is not a lot in it. If you want a better answer, why not ask the question on Stackoverflow (in fact I recommend you do, there might be an interesting better way answer)?

Omer Mor said...

Nice. However I prefer this syntax:

public static bool IsDelegate(this Type type)
{
return type.IsSubclassOf(typeof(Delegate));
}

I think IsSubclassOf() is more readable than the backward IsAssignableBy()

Mike Hadlow said...

Omer, good call. Yes, it is an easier read. I forgot about IsSubclassOf, thanks for reminding me.

Jim / Morto said...

Using IsAssignableFrom() method is the most correct.

Let's see the following example:

typeof(Delegate).IsSubClassOf(typeof(Delegate))

It returns false, because it isn't a subclass but in fact it's the class itself.

Using IsAssignableFrom, you get what is expected.

Jim / Morto said...

After testing the correct is:

public bool IsDelegate(Type type)
{
return type.IsSubClassOf(typeof(Delegate)) || type==typeof(Delegate);
}

Brandon D'Imperio said...
This comment has been removed by the author.
Brandon D'Imperio said...

This doesn't appear to work for FSharp functions unfortunately as they don't inherit from delegate or multicast delegate. I'm having a devil of a time figuring out how to include those in the IsDelegate body.

Asked related question for constraining function delegates at http://stackoverflow.com/questions/35462215/how-would-i-constrain-to-non-function