Miguel Moura
Miguel Moura

Reputation: 39474

Using Predicate<T> or a Func<T> in method to filter

Using NET Core 2.2 I have the following:

public class User {
  public virtual IEnumerable<Claim> Claims { get; }
}

public class Claim { 
  public String Type { get; set; }
  public String Value { get; set; }
}

And I have an UserService with a method FindAllClaims:

public class UserService {

  public IEnumerable<Claim> FindAllClaims(/* Some Filter */) {
  }

}

I would like to being able to filter claims in FindAllClaims method:

User user = this.User;

user.FindAllClaims(x => x.Type == "sub");

I am not sure the best way to do this ...

Using Predicate<Claim> or a Func<Claim> in FindAllClaims method?

How would I do this?

Upvotes: 2

Views: 698

Answers (2)

Phat Huynh
Phat Huynh

Reputation: 902

You can use

public IEnumerable<Claim> FindAllClaims(this IEnumerable<Claim> source, 
    Expression<Predicate<Claim>> condition)
{
    return source.Where(condition);
}

or

public IEnumerable<Claim> FindAllClaims(this IEnumerable<Claim> source, 
    Expression<Func<Claim,bool>> condition)
{
    return source.Where(condition);
}

Upvotes: 2

Zohar Peled
Zohar Peled

Reputation: 82504

The Predicate<T> delegate is defined as

public delegate bool Predicate<in T>(T obj);

The Func<T,TResult> delegate is defined as

public delegate TResult Func<in T,out TResult>(T arg);

Therefor, a Func<T, bool> is equivalent to Predicate<T>.

That being said, I would go with Predicate on this one, since it conveys the intent of the argument better than a Func.

Note, however, that the TResult of the Func delegate is marked as out, so if you're using a reference type, you can return anything that implements the TResult interface, or derived from the TResult class. For more information, read the Variance in Generic Type Parameters paragraph in the Variance in Delegates documentation.

Upvotes: 3

Related Questions