我正在尝试使用F#中的表达式(System.Linq.Expression类).以下是我遇到的问题的一个简单示例:
let blah = seq {
yield Expression.New(typedefof<'T>)
yield Expression.Constant(1)
}
Run Code Online (Sandbox Code Playgroud)
我想要的是blah成为一个seq<Expression>.然而,序列通过第一个产量推断其类型,即a NewExpression.这将导致第二个yield导致编译失败,因为它是a ConstantExpression.一个有效的解决方案是提高所有收益率:
let blah = seq<Expression> {
yield Expression.New(typedefof<'T>) :> Expression
//or
yield upcast Expression.Constant(1)
}
Run Code Online (Sandbox Code Playgroud)
但这感觉很笨拙,不得不每次都要升级.我认为灵活类型可能也是一种可能的解决方案,但我也遇到了麻烦.seq<#Expression>似乎不起作用.
有没有一种方法可以生成一系列表达式,而不必将它们中的每一个都向上转换?
正如其他人已经提到的,F#通常不会自动在代码中插入向上转换,因此您需要添加类型注释和强制转换或upcast关键字 - 我认为评论已涵盖所有选项.
编译器执行 upcast 时有两种情况- 一种是将参数传递给函数,另一种是在创建数组或列表文字时.第二个实际上可以用来简化你的例子:
let blah<'T> : Expression list =
[ Expression.New(typedefof<'T>)
Expression.Constant(1) ]
Run Code Online (Sandbox Code Playgroud)
这里,编译器Expression自动插入upcast .我想您的实际用例更复杂 - 当您需要序列表达式时yield,这将无法工作,因为那时您正在编写序列表达而不是列表文字