Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何减少二进制/lambda表达式?_C#_.net_Lambda_Expression Trees - Fatal编程技术网

C# 如何减少二进制/lambda表达式?

C# 如何减少二进制/lambda表达式?,c#,.net,lambda,expression-trees,C#,.net,Lambda,Expression Trees,我有以下功能: public double Probability(Expression<Func<double, bool>> predicate) { var expr = BinaryExpression.Lambda(predicate); // Implementation } 调试代码时,我可以看到expr如下所示: ()=>x=>(((x>3)和(x>4))和(x>5)) 我希望能够将其简化为:()=>x=>(x>5)) 问题:有什么东

我有以下功能:

public double Probability(Expression<Func<double, bool>> predicate)
{
    var expr = BinaryExpression.Lambda(predicate);  
    // Implementation
}
调试代码时,我可以看到
expr
如下所示:
()=>x=>(((x>3)和(x>4))和(x>5))

我希望能够将其简化为:
()=>x=>(x>5))

问题:有什么东西我可以开箱即用,还是必须自己实现


奖金问题:LambdaExpression和
二进制表达式
之间有什么区别?

我将从第二个问题开始。
LambdaExpression
BinaryExpression
之间有什么区别?
函数和函数中表达式之间的相同差异。
BinaryExpression是两个(二进制)节点之间的表达式

x > 5 
这是一个类型大于的二进制表达式,其左侧是一个名为x的参数,右侧是一个值为5的常量

Expression<Func<double, bool>> add = x => x > 5;
表达式add=x=>x>5;
这是一个具有二进制表达式体的lambda表达式。(选中add.Body)

对于你的问题,这是一个天真的解决方案

class Program
{
    static void Main(string[] args) {
        Expression<Func<double, bool>> predicate = x => x > 3 && x > 4;
        var visitor = new BinaryExpressionVisitor();
        predicate = (Expression<Func<double, bool>>)visitor.Visit(predicate);
    }
}

public class BinaryExpressionVisitor : ExpressionVisitor
{
    private bool root = true;
    private List<ConstantExpression> constants = new List<ConstantExpression>();
    private List<BinaryExpression> binaryExpressions = new List<BinaryExpression>();
    private HashSet<ParameterExpression> @params = new HashSet<ParameterExpression>();

    protected override Expression VisitBinary(BinaryExpression node) {
        if (IsSimpleBinaryExpression(node)) {
            binaryExpressions.Add(node);
        }
        else if (node.NodeType != ExpressionType.AndAlso) {
            return node;
        }

        if (root) {
            root = false;
            Visit(node.Right);
            Visit(node.Left);

            if (@params.Count == 1) {
                var @param = @params.ElementAt(0);
                var hashSet = new HashSet<ExpressionType>(binaryExpressions.Select(be => be.NodeType));

                if (hashSet.Count == 1) {
                    var binaryExpression = binaryExpressions[0];
                    var nodeType = binaryExpression.NodeType;
                    var constant = GetConstantByNodeType(nodeType);

                    return Expression.MakeBinary(nodeType, @param, constant);
                }
            }
        }

        return base.VisitBinary(node);
    }

    protected override Expression VisitConstant(ConstantExpression node) {
        constants.Add(node);

        return base.VisitConstant(node);
    }

    protected override Expression VisitParameter(ParameterExpression node) {
        @params.Add(node);

        return base.VisitParameter(node);
    }

    private bool IsSimpleBinaryExpression(Expression node) {
        return node.NodeType == ExpressionType.GreaterThan || node.NodeType == ExpressionType.LessThan;
    }

    private ConstantExpression GetConstantByNodeType(ExpressionType expressionType) {
        var values = constants.Select(c => c.Value);
        var value = expressionType == ExpressionType.GreaterThan ? values.Max() : values.Min();

        return Expression.Constant(value);
    }
}
类程序
{
静态void Main(字符串[]参数){
表达式谓词=x=>x>3&&x>4;
var visitor=新的二进制表达式visitor();
谓词=(表达式)visitor.Visit(谓词);
}
}
公共类BinaryExpressionVisitor:ExpressionVisitor
{
私有布尔根=真;
私有列表常量=新列表();
私有列表二进制表达式=新列表();
private HashSet@params=new HashSet();
受保护的重写表达式访问二进制(BinaryExpression节点){
if(IsSimpleBinaryExpression(节点)){
添加(节点);
}
else if(node.NodeType!=ExpressionType.AndAlso){
返回节点;
}
如果(根){
根=假;
访问(node.Right);
访问(节点左);
如果(@params.Count==1){
var@param=@params.ElementAt(0);
var hashSet=newhashset(binaryExpressions.Select(be=>be.NodeType));
if(hashSet.Count==1){
var binaryExpression=binaryExpressions[0];
var nodeType=binaryExpression.nodeType;
var常量=GetConstantByNodeType(节点类型);
返回表达式.MakeBinary(节点类型,@param,常量);
}
}
}
返回基访问二进制(节点);
}
受保护的重写表达式VisitConstant(ConstantExpression节点){
常量。添加(节点);
返回base.VisitConstant(节点);
}
受保护的重写表达式VisitParameter(ParameterExpression节点){
@参数添加(节点);
返回基本访问参数(节点);
}
私有布尔IsSimpleBinaryExpression(表达式节点){
return node.NodeType==ExpressionType.greater大于| | node.NodeType==ExpressionType.LessThan;
}
私有ConstantPression GetConstantByNodeType(ExpressionType ExpressionType){
变量值=常数。选择(c=>c.Value);
var value=expressionType==expressionType.GreaterThan?values.Max():values.Min();
返回表达式。常量(值);
}
}

你的意思是除了把你的电话改成概率(x=>x>5)?;)我不希望找到这样的东西,它本质上是优化编译器的一部分。再加上:
LambdaExpression
表示一个可以调用的方法——它有一个参数列表和一个主体。
BinaryExpression
只表示一个二进制操作——没有上下文,没有参数列表,您无法编译和调用它。看看@JonSkeetI实现的MaxBy()扩展方法,我希望能够对其调用Reduce(),但BinaryExpression上的Reduce没有任何作用。文档也不是很复杂…:-P
Reduce
与“扩展”表达式有关。见和。基本上,扩展表达式不是CLR的一部分,而是您正在做的任何事情的自定义表达式。它们通常可“还原”为CLR表达式。
class Program
{
    static void Main(string[] args) {
        Expression<Func<double, bool>> predicate = x => x > 3 && x > 4;
        var visitor = new BinaryExpressionVisitor();
        predicate = (Expression<Func<double, bool>>)visitor.Visit(predicate);
    }
}

public class BinaryExpressionVisitor : ExpressionVisitor
{
    private bool root = true;
    private List<ConstantExpression> constants = new List<ConstantExpression>();
    private List<BinaryExpression> binaryExpressions = new List<BinaryExpression>();
    private HashSet<ParameterExpression> @params = new HashSet<ParameterExpression>();

    protected override Expression VisitBinary(BinaryExpression node) {
        if (IsSimpleBinaryExpression(node)) {
            binaryExpressions.Add(node);
        }
        else if (node.NodeType != ExpressionType.AndAlso) {
            return node;
        }

        if (root) {
            root = false;
            Visit(node.Right);
            Visit(node.Left);

            if (@params.Count == 1) {
                var @param = @params.ElementAt(0);
                var hashSet = new HashSet<ExpressionType>(binaryExpressions.Select(be => be.NodeType));

                if (hashSet.Count == 1) {
                    var binaryExpression = binaryExpressions[0];
                    var nodeType = binaryExpression.NodeType;
                    var constant = GetConstantByNodeType(nodeType);

                    return Expression.MakeBinary(nodeType, @param, constant);
                }
            }
        }

        return base.VisitBinary(node);
    }

    protected override Expression VisitConstant(ConstantExpression node) {
        constants.Add(node);

        return base.VisitConstant(node);
    }

    protected override Expression VisitParameter(ParameterExpression node) {
        @params.Add(node);

        return base.VisitParameter(node);
    }

    private bool IsSimpleBinaryExpression(Expression node) {
        return node.NodeType == ExpressionType.GreaterThan || node.NodeType == ExpressionType.LessThan;
    }

    private ConstantExpression GetConstantByNodeType(ExpressionType expressionType) {
        var values = constants.Select(c => c.Value);
        var value = expressionType == ExpressionType.GreaterThan ? values.Max() : values.Min();

        return Expression.Constant(value);
    }
}