C#和VB.Net之间的表达树差异
C#和VB.Net之间的表达树差异
我有一个用于表达树的库。这个库需要同时与C#和VB.Net一起工作。
注意到两种语言在表达树构造方面有一些差异:
- 字符串比较
() => "a" == "b"
变成Expression.Equals("a", "b")
Function() "a" = "b"
变成Expression.Equals(Expression.Call(CompareString, "a", "b"), 0)
(我理解为什么VB.Net在这里使用CompareString)
- 字符串拼接
() => "a" + "b"
变成Expression.Add("a", "b", String.Concat)
Function() "a" & "b"
变成Expression.Call(String.Concat, "a", "b")
- 优化?
() => !(1 == 2)
变成Expression.Not(Expression.Equals(1, 2))
Function() Not (1 = 2)
变成Expression.NotEqual(1, 2)
我的库处理了所有这些差异,但还有其他差异我需要注意吗?
编辑
我的代码的一些解释。
我所使用的系统有一个用于指定文档过滤器的过滤器,像这样:
var filter = document.Filter; filter.LeftParanthesis(); filter.Column(columnNumber); filter.Equals(); filter.Value("abc"); filter.RightParanthesis(); filter.And(); filter.LeftParanthesis(); ... document.Refresh();
为了更容易使用过滤器,我的代码允许您将过滤器指定为Expression
lambda。
Expression> filter = () => (123.AsStringColumn() == "abc") && (...); filter.Apply(document);
然后,我的代码遍历表达树并按照上述指定的方式调用文档过滤器方法。
过滤器不支持您可以放入lambda表达式的所有内容。方法调用是最明显的一个。
因为VB.Net在某些情况下生成方法调用,而C#不会,所以我需要拦截这些并以不同的方式处理。
在我的项目中,我经常需要使用C#和VB.Net进行工作,而且我发现大多数的差异都出现在VB.Net处于不安全模式时。也就是说,如果我们将VB.Net设置为类型安全模式(选项strict打开,选项explicit打开...选项all打开),它将和C#一样工作。
对于C#和VB.Net之间的表达式树,存在一些差异。下面是一些主要的差异和解决方法:
1. 表达式树的创建方式:
- C#中,可以使用lambda表达式来创建表达式树。例如:
Expression> expression = x => x > 5;
- VB.Net中,可以使用AddressOf运算符和匿名函数来创建表达式树。例如:
Dim expression As Expression(Of Func(Of Integer, Boolean)) = Function(x) x > 5
2. 表达式树的调用方式:
- C#中,可以使用Compile方法将表达式树编译为委托,并调用该委托。例如:
Funcfunc = expression.Compile(); bool result = func(10);
- VB.Net中,可以直接调用表达式树。例如:
Dim result As Boolean = expression(10)
3. 表达式树中的类型推断:
- C#中,表达式树中的类型推断相对较强,可以自动推断出lambda表达式的参数类型。例如:
Expression> expression = x => x > 5;
- VB.Net中,表达式树中的类型推断相对较弱,需要显式指定lambda表达式的参数类型。例如:
Dim expression As Expression(Of Func(Of Integer, Boolean)) = Function(x As Integer) x > 5
通过了解这些差异,并根据需要选择合适的方法,我们可以在C#和VB.Net之间更轻松地进行表达式树的操作。无论是使用lambda表达式还是匿名函数,我们都可以根据项目的需要来选择适合的方式。同时,我们还可以根据表达式树中的类型推断差异来注意在VB.Net中显式指定参数类型。这样,我们就可以更好地利用表达式树的功能,提高代码的效率和可读性。
在C#和VB.Net中,/
除法运算符的工作方式不同。在C#中,它根据使用的数据类型进行自适应,而在VB中总是将操作数转换为浮点数值:
() => 1 / 2
变成 Expression.Divide(1, 2)
Function() 1 / 2
变成 Expression.Divide(Expression.Convert(1, Double), Expression.Convert(2, Double))
在VB中,您需要使用\
运算符进行整数除法,使用/
进行浮点数除法,以获得与C#中/
运算符相同的结果。
谢谢。我认为处理这个问题(对我来说)最好的方法是在转换错误消息中提到它。
对不起。VB的怪癖让我发疯 - 我是说 - 一个反斜杠?呃!