Coder Perfect

Why did you choose FuncT,bool> over PredicateT>?

Problem

This is just a curious question to which I was hoping for a good answer:

These two methods, for example, are available in the.NET Framework Class Library:

public static IQueryable<TSource> Where<TSource>(
    this IQueryable<TSource> source,
    Expression<Func<TSource, bool>> predicate
)

public static IEnumerable<TSource> Where<TSource>(
    this IEnumerable<TSource> source,
    Func<TSource, bool> predicate
)

Why don’t they use PredicateTSource> instead of FuncTSource, bool>? PredicateTSource> appears to be used solely by ListT> and ArrayT>, however FuncTSource, bool> appears to be used by almost all Queryable and Enumerable methods and extension methods… what gives?

Asked by Svish

Solution #1

Predicate was introduced at the same time as ListT> and ArrayT> in.net 2.0, but the various Func and Action variations were introduced in.net 3.5.

As a result, the Func predicates are mostly employed in LINQ operators to ensure consistency. The following is the.net 3.5 guideline for utilizing FuncT> and ActionT>:

Answered by Jb Evain

Solution #2

This is something I’ve always wondered about. I like the PredicateT> delegate since it’s clear and concise. However, you must consider the Where: overloads.

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

This also allows you to filter based on the entry’s index. This is nice and consistent, as opposed to:

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

wouldn’t be.

Answered by Jon Skeet

Solution #3

The real reason for choosing Func instead of a specific delegate is that C# interprets delegate declarations as whole different types.

Despite having identical argument and return types, Funcint, bool> and Predicateint> are not assignment compatible. As a result, if each library declares its own delegate type for each delegate pattern, the libraries will be unable to communicate unless the user adds “bridging” delegates to conduct conversions.

    // declare two delegate types, completely identical but different names:
    public delegate void ExceptionHandler1(Exception x);
    public delegate void ExceptionHandler2(Exception x);

    // a method that is compatible with either of them:
    public static void MyExceptionHandler(Exception x)
    {
        Console.WriteLine(x.Message);
    }

    static void Main(string[] args)
    {
        // can assign any method having the right pattern
        ExceptionHandler1 x1 = MyExceptionHandler; 

        // and yet cannot assign a delegate with identical declaration!
        ExceptionHandler2 x2 = x1; // error at compile time
    }

Microsoft hopes that pushing everyone to use Func will solve the problem of incompatible delegate types. Because they will only be matched based on their parameter/return types, everyone’s delegates will get along swimmingly.

Because Func (and Action) cannot contain out or ref parameters, it does not answer all difficulties, but those are less typically used.

Update: Svish says in the comments:

Yes, as long as your application just assigns methods to delegates, which is what my Main function does in the first line. The compiler generates code in the background to create a delegate object that is passed to the method. So I could update x1 to be of type ExceptionHandler2 without causing a problem in my Main function.

On the second line, however, I attempt to reassign the first delegate to a different delegate. Despite the fact that the second delegate type has the identical parameter and return types as the first, the compiler generates error CS0029: Type ‘ExceptionHandler1’ cannot be implicitly converted to ‘ExceptionHandler2’.

Perhaps this will help to clarify things:

public static bool IsNegative(int x)
{
    return x < 0;
}

static void Main(string[] args)
{
    Predicate<int> p = IsNegative;
    Func<int, bool> f = IsNegative;

    p = f; // Not allowed
}

As long as I assign my method IsNegative straight to the p and f variables, everything is OK. However, I am unable to assign one of the variables to the other.

Answered by Daniel Earwicker

Solution #4

The recommendation (in 3.5 and higher) is to utilize Action…> and Func…> – for the “why?” – questions. One advantage is that “PredicateT>” is only useful if you know what “predicate” means; otherwise, you’ll have to look up the signatute in an object-browser (or something similar).

In contrast, FuncT,bool> follows a typical pattern; I can determine right away that this is a function that accepts a T and returns a bool – no need to know any jargon, just use my truth test.

This would have sufficed for “predicate,” but I appreciate the effort to standardize. It also allows for a great deal of parity with related methods in that field.

Answered by Marc Gravell

Post is based on https://stackoverflow.com/questions/665494/why-funct-bool-instead-of-predicatet