Stop creating custom delegate types

Note to OSS and framework developers:

Please stop creating custom delegate types.  Use the Action and Func delegates instead.

The problem is that delegate types with the same signature are not convertible to each other.  For example, none of these assignments will work:

public delegate bool CustomMatchingFunction(string value);

public void Custom_delegates_are_bad()
{
    Predicate<string> match1 = value => value == "Blarg";
    Func<string, bool> match2 = value => value == "Blarg";
    CustomMatchingFunction match3 = value => value == "Blarg";

    match1 = match2;
    match1 = (Predicate<string>)match2;
    match1 = match3;
}

Although all of the delegate types shown have the same signature, this does not mean that they’re the same type.  They’re neither implicitly nor explicitly convertible from each other.  One of the preliminary LINQ framework design guidelines states:

Do use the new LINQ types “Func<>” and “Expression<>” instead of custom delegates and predicates, when defining new APIs.

There are Action delegates for void methods and Func delegates for methods that return values.  If something needs a delegate, use either the generic or specific versions of these delegate types.  Instead of “Predicate<T>”, use “Func<T, bool>”.  Instead of creating a custom void delegate, use “Action”.

By creating custom delegate types, you’re forcing people using your API to either force your custom type into their code, or force them to use a bunch of “wrapper methods” that wrap, convert and call your custom delegate type.

If you declare even a single delegate type in your code (and you’re using .NET 3.5), stop and make sure there isn’t already an Action or Func delegate that works for you.

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Jimmy Bogard

I'm a technical architect with Headspring in Austin, TX. I focus on DDD, distributed systems, and any other acronym-centric design/architecture/methodology. I created AutoMapper and am a co-author of the ASP.NET MVC in Action books.
This entry was posted in C#. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://www.peterRitchie.com/blog Peter Ritchie

    …after you upgrade to Visual Studio 2008…

  • http://www.lostechies.com/blogs/joe_ocampo/ Joe Ocampo

    Nice. I am surprised R#4 doesn’t catch this, in its hints.

  • http://www.elegantcode.com Jarod

    It is a personal goal to never type the word ‘delegate’ in an IDE again :)

    Func<>/Action is kind of addicting though, they are so easy I find myself wanting to use them were I would have not considered a delegate in the past.

  • http://jimmybogard.lostechies.com Jimmy Bogard

    @Peter

    Yeah yeah…let’s just pretend that everyone upgrades to .NET 3.5 immediately.

    I wanted to get some comments back from the FDG folks to see what they might recommend for .NET 2.0 situations…but these custom delegates can be a real pain…

  • http://msmvps.com/jon.skeet Jon Skeet

    It’s not quite as bad as you’re making it out to be. Yes, there’s no direct conversion – but you don’t need to write any extra methods to convert from one to another. The following assignments both work:

    match1 = new Predicate(match2);
    match1 = new Predicate
    (match3);

    No wrapper methods required.

    That said, I do agree that it’s best not to create your own delegate types by and large.

    Jon

  • Bart Czernicki

    Uhh…no. 2 reasons:

    - backwards compatibility:
    I could list you a few examples why u still would want custom delegate types, but say ur maintaining an API that has to work with 2.0 code…why exactly would u start using Func/Action??

    Same goes for automatic properties, collection initializers, implicit anon types…all the “syntactic sugar” for C# 3.0

    - standards:

    The achitect should define what the best practices are and code standards are. If you ur standards are to write code a specific way and then u have developers auto update their code to what they see on a blog, ur going to have bigger problems

  • http://www.codethinked.com Justin Etheredge

    Here here, that is an excellent suggestion for those working on a completely 3.5 codebase.

  • http://jimmybogard.lostechies.com Jimmy Bogard

    @Jon

    Hooray! I knew someone would find a way for it to work easily. Thanks!

  • http://jimmybogard.lostechies.com Jimmy Bogard

    @Jon

    Hooray! I knew someone would find a way for it to work easily. Thanks!

  • http://jimmybogard.lostechies.com Jimmy Bogard

    @Bart

    Many of the C# 3.0 features work just fine with .NET 2.0. C# 3.0 still compiles to the CLR 2.0. It’s just not as nice :)

    Yes, this only applies to .NET 3.5. It’s still annoying creating these custom types, especially when you have APIs that expose properties and methods that are designed to work with Action/Func and something has to translate.

  • Bart Czernicki

    @bogardj

    “many” is the keyword here.

    I completely agree that Func/Action provide u enough overrides to not have to create a delegate. Even if, you have a method that takes 8 parameters u should be passing in an object instead probably and using a Func/Action

    However, with having a mixed dev environment 2005/2008 (which we are transitioning from) it would cause MAJOR coding horrors if we had developers go on blogs and simply apply what a few people agree is a good practice.

  • http://grabbagoft.blogspot.com Jimmy Bogard

    @Bart

    If you have developers applying wholesale advice from what they read on blogs, I think your problem is in the personnel/training department.

    This isn’t just my advice, it comes from Microsoft’s Framework Design Guidelines folks as well. It applies only to .NET 3.5 environments.

  • http://realfiction.net Frank Quednau

    Recently I encountered one issue with generic delegates: They cannot be marshalled to static external functions imported from some dll. In this case you will have to define your own non-generic delegate even though you may have a fitting one.

  • http://poundingcode.com John Hughes

    The use of Action gives no implicit meaning of that the parameters are as opposed to a custom delegate. I personally think custom delegates are the way to go if you are exposing an API to the outside world.