所以这是我在使用表达式和函数时观察到的奇怪行为.
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]);