添加委托:添加两个Func <T,TResult>时出现意外结果

Meg*_*ark 4 c# expression operators func

所以这是我在使用表达式和函数时观察到的奇怪行为.

public int Age { get; set; }
public EyeColor EyeColor { get; set; }
public int Weight { get; set; }

public Func<Person, bool> AgeAndEyesMatch
    {
        get { return IsPersonYoung().Compile() + PersonHasRightEyeColor().Compile(); }
    }

public Func<Person,bool> AgeAndWeightMatch
    {
        get { return IsPersonYoung().Compile() + IsPersonInShape().Compile(); }
    } 

private Expression<Func<Person, bool>> PersonHasRightEyeColor()
    {
        return person => person.EyeColor == EyeColor;
    }

private Expression<Func<Person, bool>> IsPersonYoung()
    {
        return person => person.Age <= Age;
    }

private Expression<Func<Person, bool>>  IsPersonInShape()
    {
        return person => person.Weight <= Weight;
    } 
Run Code Online (Sandbox Code Playgroud)

在控制台应用程序中,我创建了以下"人物"

var mark = new Person
        {
            Age = 30,
            EyeColor = EyeColor.Blue,
            Height = 69,
            Name = "Mark",
            Weight = 185
        };
var austin = new Person
            {
                Age = 70,
                EyeColor = EyeColor.Brown,
                Height = 64,
                Name = "Austin Powers",
                Weight = 135
            };
var napolean = new Person
        {
            Age = 17,
            EyeColor = EyeColor.Green,
            Height = 71,
            Name = "Napolean Dynamite",
            Weight = 125
        };
Run Code Online (Sandbox Code Playgroud)

主程序列出这些人员并称其为"人员",只是要求用户提供年龄,眼睛颜色和体重的搜索参数.然后按如下方式调用人员列表:newList = people.Where(person => coolKidCriteria.AgeAndEyesMatch(person)).ToList(); 并且newNewList = people.Where(person => coolKidCriteria.AgeAndWeightMatch(person)).ToList();

给定MaxAge = 20的参数,EyeColor = EyeColor.Blue,MaxWeight = 150,我希望第一个列表为空,第二个列表只包含Napolean Dynamite ......但是我收到第一个用Mark填充的列表,第二个列表填充了Austin Powers和Napolean Dynamite ......我能想到的意外行为的唯一原因是两个Func的'+'运算符导致了问题.只是想知道是否有人可以解释原因.我推断出只评估了两者中的第二个函数:AgeAndEyeColor =(年龄不评估)+(仅适用于Mark的眼睛颜色匹配)和AgeAndInShape =(年龄不评估)+(Austin和Napolean .InShape = =真)

我为应用程序的歧视语气道歉...这对我来说只是一个学习的东西,我没有其他背景.

Raw*_*ing 5

当你+在两个Func<int, bool>s 上使用时,你并没有告诉C#创建一个Func<int, bool>调用你的两个原始函数的单个&&结果.相反,您告诉C#创建一个调用这两个函数并返回最后结果多播委托.

例如,

static Func<int, bool> Fizz = i => i % 3 == 0;
static Func<int, bool> Buzz = i => i % 5 == 0;
static Func<int, bool> FizzBuzz = Fizz + Buzz;

static void Main(string[] args)
{
    var fiveIsFizzBuzz = FizzBuzz(5); // gives true
}
Run Code Online (Sandbox Code Playgroud)

如果你想要&&,你必须手动完成:

static Func<int, bool> FizzBuzz = i => Fizz(i) && Buzz(i);
Run Code Online (Sandbox Code Playgroud)

如果所有内容都必须是表达式,则可以使用以下内容:

static Expression<Func<int, bool>> Fizz = i => i % 3 == 0;
static Expression<Func<int, bool>> Buzz = i => i % 5 == 0;
static Expression<Func<int, bool>> FizzBuzz = Expression.Lambda<Func<int, bool>>(
    Expression.AndAlso(Fizz.Body, Expression.Invoke(Buzz, Fizz.Parameters[0])),
    Fizz.Parameters[0]);
Run Code Online (Sandbox Code Playgroud)

  • @MegaMark真是太遗憾了.如果我说我100%理解了最后一点(为什么你必须用第一个参数调用第二个表达式?),我会撒谎.但是我已经尝试使用你的风格在一个整数列表中使用我的Fizzbuzz了.哪里`,它对我有用.你得到什么错误? (2认同)