I'm a bit new both to the C# team and to blogging, so bear with me as I muddle through my first post about something that interests me. :)Let me start at the beginning. Since C# 1.0, one of the things that I liked about it (compared to Java, since I'm an OO nerd) was the fact that it had a way to pass functions from one place to another. However, delegate types hardly provided the ease of code passing that my functional background would like, and with Java, anonymous inner classes at least provided a simple way of writing a bit of code in a method, including closing over some of the local state, and passing that to another method. Of course, the downside was that I always kept an IFunction interface around, which specified a single method from object to object (and, once I started using the Sun's JSR-14 comiler, from T to U) that I could instantiate as needed for my code passing requirements.C# 2.0's anonymous methods made that IFunction type look clunky with all of Java's extra syntax required to create an anonymous inner class. As with the IFunction type in Java, however, I needed a delegate type for the signature of any method that needed to accept code as an argument. No big deal, just requires writing a line declaring that delegate type above the function, and thanks to implicit conversion from anonymous methods to an appropriate delegate type, I never needed to think about that type name again, unless it came up in error messages (usually due to the limitations of the type inference that goes on when generic delegate types are combined with polymorphic methods--but this is an issue for another blog entry). The convenience of not having to write a new method every time I wanted to create a delegate combined with the intuitive power of closures (well, almost closures--but this is a well-covered issue that I don't want to reiterate here) made me that much more productive when coding.Now to the main event. Since the PDC, I've heard a lot of buzz surrounding all of the various "function" delegate types that are included in the LINQ preview. I'm sure those of you with any experience with functional programming are breathing sighs of relief that such obvious types are finally being included in the .NET framework--I know I am! Still, along with this relief is a healthy dose of caution. I find myself wary of how these types will integrate into the existing framework, with all of its predefined delegate types. For example, suppose I write a method using the LINQ framework that accepts Func<int, bool>, and am interested in using this function to filter a List<int> that I already have. Looking down the IntelliSense-provided options suggests that the FindAll method will perform the action that I want. So I call FindAll on my list and pass it my Func<int, bool>. But what's this? The compiler is telling me that Func<int, bool> cannot be converted to Predicate<int>! That's ridiculous: I have a predicate, at least conceptually. Really, what's the difference between a Predicate<int> and a Func<int, bool>? Both represent a function that takes an int and returns a bool, so why aren't they compatible?I had mistakenly convinced myself that methods really were just as powerful in C# as they are in Lisp. All the ease of using delegates that came with anonymous methods and implicit conversions to delegate types had blinded me to their original flaw--that despite their ease of use, methods are still not first-class entities. Because the language doesn't consider a method an actual type, despite the fact that the same method could be converted to either a Func<int, bool> or a Predicate<int>, you can't simply convert one to the other. Of course, thanks to anonymous methods, and more recently, lambda expressions, this isn't hard to work around. Given a Func<int, bool> func, you can create a Predicate<int> simply by saying arg => func(arg). But having to write the identity function still feels awkward, and reduces the functional appeal of your program.Where am I going with all this? Well, even without fully first-class method support, it would have been nice if the Func<> types had been included in the framework since v1.0. Of course, this wasn't possible before 2.0 (hooray for generics!), and I guess no one thought they'd be important enough to add for Whidbey. Maybe they're right on that point; it does seem like very few C# programmers use delegates in their APIs.
I suppose the real bottom line is that I need to bear in mind the distinction between methods, which are the actual code that take and return arguments, and delegates, which merely encapsulate a method (or several methods--but once again, this is not an issue for this post). This distinction is subtle, but anyone who programs in C# should understand it.