Delegates and Predicate enquiry

2019-03-06 13:51发布

问题:

I'm learning about lambdas and I'm trying to understand why, while having EmployeeFilterAge class like so:

public class EmployeeFilterAge
{
    int _age;
    public EmployeeFilterAge(int age)
    {
        _age = age;
    }
    public bool OlderThan(Employee employee)
    {
        return employee._age > _age;
    }
}

when I'm trying to do this:

var filterByAge = new EmployeeFilterAge(29);
var del = new AgeExclusion(filterByAge.OlderThan);

I get an error saying "no overload method ... matches delegate ...", while delegate looks like that:

public delegate bool AgeExclusion(object person);

Is this because its a predicate?

回答1:

The delegate says that the parameter can be of any type. When someone invokes the method they can pass in a Lion, a Tiger, a Bear (Oh My!!!), or whatever else they want, and your method needs to be able to handle it.

You're trying to assign a method that can only ever accept an Employee, and that isn't allowed to accept any other type as an argument, so obviously it's not a valid method to assign to a variable of that delegate type.

Now if the types were reversed, it would be fine. If the delegate said that it could accept a method that takes only an Employee as an argument, then you could give it a method that is able to take anything as an argument, because after all, all of the employees that it will pass it would be valid arguments for a method that can accept anything. The technical term for this is contravariance.



回答2:

You are trying to pass a method group that takes an Employee for a delegate that takes an object. This is not allowed because the user of the delegate is allowed to pass an object, while the delegate expects an Employee.

Here is how you can fix it:

AgeExclusion del = e => filterByAge.OlderThan((Employee)e);

Demo.