Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/335.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/blackberry/2.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# 表达式与运算符&&;_C#_Lambda - Fatal编程技术网

C# 表达式与运算符&&;

C# 表达式与运算符&&;,c#,lambda,C#,Lambda,我有一个类,它的工作原理有点像LINQtoSQLWhere子句 它从表达式树构建一系列操作 表达式树是一个表达式(即不带参数的lambda,返回bool) 该类适用于上述示例中的normal表达式,但现在我需要组合表达式的功能 我添加了和或类似的方法 var exp1 = () => x != 3; var exp2 = () => y != 5; var exp = ConditionBuilder.And(exp1, exp2); 但当组合多个表达式时,情况会变得复杂 我想写信

我有一个类,它的工作原理有点像LINQtoSQL
Where
子句

它从表达式树构建一系列操作

表达式树是一个
表达式(即不带参数的lambda,返回bool)

该类适用于上述示例中的
normal
表达式,但现在我需要组合表达式的功能

我添加了和或类似的方法

var exp1 = () => x != 3;
var exp2 = () => y != 5;
var exp = ConditionBuilder.And(exp1, exp2);
但当组合多个表达式时,情况会变得复杂

我想写信

var exp=exp1&&exp2

但是由于我不能直接重载操作符&&我需要找到其他的解决方案。 棘手的部分是,结果操作没有按位运算符的布尔重载。i、 e.exp1和exp2的结果是int而不是bool。(我可以通过添加
!=0来解决此问题)

因此,我现在的问题是:

  • 如果我让运算符&成为逻辑表达式(即AndAlso),会让人困惑吗
  • 如果重载&/true/false,运算符&&将起作用,但这也将创建隐式布尔转换。我知道隐式布尔转换是C++中想要避免的,但我不确定它是如何重要的。此外,被重写的true和false是否应该评估表达式?(即如果(exp1)
做什么?) 编辑: 我已经有这样的工作代码:

public class ConditionBuilder
{
    private readonly Expression<Func<bool>> _filter;

    public ConditionBuilder(Expression<Func<bool>> filter) {
        _filter = filter;
    }

    public static ConditionBuilder And(ConditionBuilder left, ConditionBuilder right) {
        return new ConditionBuilder(Expression.Lambda<Func<bool>>(Expression.AndAlso(left._filter.Body, right._filter.Body)));
    }

    public static ConditionBuilder Or(ConditionBuilder left, ConditionBuilder right) {
        return new ConditionBuilder(Expression.Lambda<Func<bool>>(Expression.OrElse(left._filter.Body, right._filter.Body)));
    }
}
是有效的表达式,但

() => x != 3 & y != 5
事实并非如此


第二个问题是,如果对BoL隐式转换会导致C++中的问题,就像C++中的问题。

我会超载<代码>和<代码>操作符。这并不令人困惑,因为

&
可以是逻辑的,也可以是按位的,具体取决于上下文

要重载
&
运算符,您必须为重载运算符使用包装类(例如
条件生成器

您可以在true运算符的文档中看到重载各种运算符的完整示例,包括
&


使用
ConditionBuilder
演示重载
&
运算符的简单示例

这给出了一个语法,比如
var exp3=exp1.And(exp2)
比原始版本更整洁,并且链接合理
exp1.和(exp2).和(exp3)

在混合和/或混合时必须小心,因为
exp1.或(exp2).和(exp3)
将为您提供
(exp1 | exp2)&exp3
,而不是
exp1 |(exp2&exp3)
。这可以通过使用显式括号来避免,例如
(exp1.或(exp2))和(exp3)
vs
exp1.或(exp2.和(exp3))


支持问题&& 要支持
&
,您需要在ConditionBuilder中支持
true
false
运算符,这意味着编译和执行表达式

public static bool operator true (ConditionBuilder left) {
    return left.Execute();
}

public static bool operator false (ConditionBuilder left) {
    return !left.Execute();
}
使用LinqPAD测试时,来自
var exp3=exp1和&exp2
的结果不太理想

  • 必须立即执行exp1以解决短路问题
  • exp1为true时,结果表达式等价于:
    var exp3=()=>x!=3&&y!=5
  • exp1为false时,结果表达式等效于:
    var exp3=()=>x!=3

  • 这将不起作用,因为它将创建lambda而不是表达式。请看我的编辑抱歉,我只是使用了
    Func
    ,因为它非常简单,可以编写一个简短的示例,您可以拥有并返回任何东西,例如
    返回条件生成器。并且(lhs,rhs)
    我已经更改了示例以使用示例条件生成器。您确定&如果(lhs()==true)else rhs()
    ,则计算结果为
    ?我的猜测可能会像be
    if(true(lhs))操作符&(lhs,rhs)
    这样,我已经修正了答案。通过使用LINQPad进行测试,看起来它实际上是编译成这样的东西
    if(false(lhs))lhs-else操作符&(lhs,rhs)
    意识到表达式库本身有
    等,对于相同类型的功能,我会小心选择操作符重载。你说“当组合多个表达式时会变得复杂”,但是操作符重载的等价物,虽然在使用点上更简洁,但肯定会更难创建和调试,不是吗?
    
    () => x != 3 & y != 5
    
    void Main ()
    {
        int x = 1;
        int y = 1;
    
        var exp1 = new ConditionBuilder (() => x != 3);
        var exp2 = new ConditionBuilder (() => y != 5);
        var exp3 = exp1 & exp2;
    
        Console.WriteLine (exp3.Execute ());
    }
    
    public class ConditionBuilder
    {
        private readonly Expression<Func<bool>> _filter;
    
        public ConditionBuilder(Expression<Func<bool>> filter) {
            _filter = filter;
        }
    
        public bool Execute() {
            return _filter.Compile()();
        }
    
        public static ConditionBuilder And(ConditionBuilder left, ConditionBuilder right) {
            return new ConditionBuilder(Expression.Lambda<Func<bool>>(Expression.AndAlso(left._filter.Body, right._filter.Body)));
        }
    
        public static ConditionBuilder Or(ConditionBuilder left, ConditionBuilder right) {
            return new ConditionBuilder(Expression.Lambda<Func<bool>>(Expression.OrElse(left._filter.Body, right._filter.Body)));
        }
    
        public static ConditionBuilder operator & (ConditionBuilder left, ConditionBuilder right) {
            // Note this could confuse users for the problem discussed below.
            // Consider using Expression.And instead of AndAlso
            return ConditionBuilder.And(left, right);
        }
    
        public static ConditionBuilder operator | (ConditionBuilder left, ConditionBuilder right) {
            // Note this could confuse users for the problem discussed below.
            // Consider using Expression.Or instead of OrElse
            return ConditionBuilder.Or(left, right);
        }
    }
    
    public ConditionBuilder And(ConditionBuilder right) {
        return new ConditionBuilder(Expression.Lambda<Func<bool>>(Expression.AndAlso(_filter.Body, right._filter.Body)));
    }
    
    public static bool operator true (ConditionBuilder left) {
        return left.Execute();
    }
    
    public static bool operator false (ConditionBuilder left) {
        return !left.Execute();
    }