Thursday, 21 January 2010

Func vs Predicate

These last days I've been giving a short course on .Net development at work to some colleages with a Java background (poor guys, having had to listen to my ramblings on programming sure has not been an easy task :-)

Thing is that having talked first about the generic delegate types (Predicate<T>, Action<...> and Func<...>), when then I moved to Linq to Objects and showing a sample with the Where method, I was assuming this method would expect a Predicate<T>. So, when I opened the SDK documentation it came as a surprise to me that in fact it expects a Func<T, bool> (normally you just use a lambda and let the compiler the task of replacing it with the appropiate delegate, so you don't need to pay much attention to the specific delegate type used).
If we already have a Predicate<T> type, that returns a bool, and which name follows semantics commonly used in other environments for similar purposes, a function returning true or false, what's the sense of using Func<T, bool>?
It seems less meaningful to me (OK, you inmediately read the bool thing, but anyway Predicate seems more clear to me).

Of course, this is a rather unoriginal question that many other have done before, so checking this thread in stackoverflow, I found an explanation by Jon Skeet that I rather like:


I've wondered this before. I like the Predicate delegate - it's nice and descriptive. However, you need to consider the overloads of Where:

Where<T>(IEnumerable<T>, Func<T, bool>)
Where<T>(IEnumerable<T>, Func<T, int, bool>)

That allows you to filter based on the index of the entry as well. That's nice and consistent, whereas:

Where<T>(IEnumerable<T>, Predicate<T>)
Where<T>(IEnumerable<T>, Func<T, int, bool>)

wouldn't be.


Based on other answers, we could think that if Predicate<T> and Func<...> had been introduced in the same version of the Framework, maybe Predicate<T> would have not made it in favor of Func<T, bool>, but well, there are other cases where having a Delegate Type with a very semantic name has seemed useful to the Framework Architects, that's the case of Converter<TInput, TOutput> that could have been omitted in favor of Func<TInput, TOutput>.

No comments:

Post a Comment