无法让运算符重载与 Linq 表达式树一起使用
我正在从 F# 创建 Linq 表达式树,该树对我拥有的自定义数据类型进行操作。该类型是一个非常简单的可区分联合,它重载了常用的算术运算符。但由于某种原因,我无法创建算术 linq 表达式节点,因为它找不到正确的重载。问题是,我发誓我不久前就已经开始工作了,但我不知道我做了什么改变才使它崩溃。
我将附上一个显示问题的小代码示例。下面的数据类型重载了加法运算符。使用重载运算符就像一个魅力,但是当我尝试使用 Expression.Add(lhs, rhs) 创建加法表达式树节点时,系统会抛出一个异常,抱怨它找不到 Add 操作的重载。
有人知道我做错了什么吗?
谢谢你, 里卡德
open System.Linq.Expressions
module DataType =
exception NotImplementedYet of string
type DataCarrier =
| ScalarCarrier of float
| VectorCarrier of float array
member this.Add(other) =
match (this, other) with
| ScalarCarrier(x), ScalarCarrier(y) -> ScalarCarrier(x + y)
| VectorCarrier(u), VectorCarrier(v) ->
VectorCarrier(Array.map2 (fun x y -> x + y) u v)
| _,_ -> raise (NotImplementedYet("No go!"))
static member (+) (lhs:DataCarrier, rhs) =
lhs.Add(rhs)
module Main =
let createAddOp (lhs:DataType.DataCarrier) (rhs:DataType.DataCarrier) =
let clhs = Expression.Constant(lhs)
let crhs = Expression.Constant(rhs)
Expression.Add(clhs, crhs)
(* no problems with this one *)
printf "Testing operator overloading: %A" (DataType.ScalarCarrier(1.0)
+ DataType.ScalarCarrier(2.0))
(* this throws an exception *)
printf "Testing expr construction %A" (Main.createAddOp
(DataType.ScalarCarrier(1.0))
(DataType.ScalarCarrier(2.0)))
I am creating Linq expression trees from F# that operates on a custom datatype I have. The type is a very simple discriminated union that has the usual arithmetic operators overloaded. But for some reason I cannot create arithmetic linq expression nodes due to the fact that it can't find the correct overload. Thing is, I swear I had this working some time ago but I can't figure out what I changed to make it break.
I'll attach a small code sample showing the problem. The datatype below has the Addition operator overloaded. Using the overloaded operator works like a charm, but when I try to create an addition expression tree node using Expression.Add(lhs, rhs) the system throws an exception complaining that it can't find the overload for the Add operation.
Does anyone have an idea of what I am doing wrong?
Thank you,
Rickard
open System.Linq.Expressions
module DataType =
exception NotImplementedYet of string
type DataCarrier =
| ScalarCarrier of float
| VectorCarrier of float array
member this.Add(other) =
match (this, other) with
| ScalarCarrier(x), ScalarCarrier(y) -> ScalarCarrier(x + y)
| VectorCarrier(u), VectorCarrier(v) ->
VectorCarrier(Array.map2 (fun x y -> x + y) u v)
| _,_ -> raise (NotImplementedYet("No go!"))
static member (+) (lhs:DataCarrier, rhs) =
lhs.Add(rhs)
module Main =
let createAddOp (lhs:DataType.DataCarrier) (rhs:DataType.DataCarrier) =
let clhs = Expression.Constant(lhs)
let crhs = Expression.Constant(rhs)
Expression.Add(clhs, crhs)
(* no problems with this one *)
printf "Testing operator overloading: %A" (DataType.ScalarCarrier(1.0)
+ DataType.ScalarCarrier(2.0))
(* this throws an exception *)
printf "Testing expr construction %A" (Main.createAddOp
(DataType.ScalarCarrier(1.0))
(DataType.ScalarCarrier(2.0)))
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
一种解决方案是显式键入表达式操作数(为它们提供静态类型
DataType.DataCarrier
而不是其运行时类型DataType.DataCarrier.ScalarCarrier
):另一种选择是显式键入传递加法运算符来使用:
不过,我很惊讶您的原始代码不起作用。这似乎是表达式树如何查找相关添加运算符的限制(也就是说,Linq 似乎仅在操作数的运行时类型上查找添加运算符)。
One solution is to explicitly type the Expression operands (giving them the static type
DataType.DataCarrier
instead of their runtime typeDataType.DataCarrier.ScalarCarrier
):Another option would be to explicitly pass the addition operator to use:
I am surprised that your original code doesn't work, though. It appears to be a limitation in how expression trees find relevant add operators (that is, it appears that Linq only looks for add operators on the runtime types of operands).