c# – 添加委托:添加两个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;
    } 

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

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
        };

主程序列出这些人员并称其为“人员”,只是要求用户提供年龄,眼睛颜色和体重的搜索参数.然后按如下方式调用人员列表: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 == true )

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

解决方法:

当你在两个Func< int,bool> s上使用时,你并没有告诉C#创建一个Func< int,bool>它将您的两个原始功能和&& s称为结果.相反,您告诉C#创建一个调用两个函数并返回最后结果的multicast delegate.

例如,

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
}

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

static Func<int, bool> FizzBuzz = i => Fizz(i) && Buzz(i);

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

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]);
上一篇:Python中模运算符的时间复杂度


下一篇:JavaScript运算符优先逻辑让我很困惑