有没有办法以某种方式重载函数?
让我们看看这 3 个函数:
// Returns StringPropertyInfo
let stringProperty (expr:Expr<'a -> string>) (cfg:EntityInfo<'a>) =
cfg.Property expr
// Returns DatePropertyInfo
let dateProperty (expr:Expr<'a -> System.DateTime>) (cfg:EntityInfo<'a>) =
cfg.Property expr
// Returns BytePropertyInfo
let byteProperty (expr:Expr<'a -> System.Byte>) (cfg:EntityInfo<'a>) =
cfg.Property expr
有没有办法将它们全部合并为:
let property expr cfg = ....
如果没有,完成类似事情的最巧妙的方法是什么?
最佳答案
如果您想使用基于受歧视联合的方法,那么我认为声明更合适(因为您不需要使用引号进行操作)。对 Alex 建议的类型稍作修改是:
type PropertyInfo<'a> =
| String of Expr<'a -> string>
| Date of Expr<'a -> System.DateTime>
| ...
然后你会写这样的内容:
let property (pi:PropertyInfo<'a>) (cfg:EntityInfo<'a>) =
match pi with
| String e -> cfg.Property e
| ...
cfg |> property (String <@ fun e -> e.Foo @>)
另一种选择是将 property
实现为类型的静态成员,在这种情况下,您可以使用常用的重载(类似于 C#)。像这样的东西:
type EF =
static member property (expr:Expr<'a -> string>) (cfg:EntityInfo<'a>) =
cfg.Property expr
static member property (expr:Expr<'a -> System.DateTime>) (cfg:EntityInfo<'a>) =
cfg.Property expr
static member property (expr:Expr<'a -> System.Byte>) (cfg:EntityInfo<'a>) =
cfg.Property expr
然后你会写:
cfg |> EF.property <@ e -> e.Foo @>
最后,您还可以通过使函数完全通用并进行动态类型测试(以决定使用什么返回类型)来使其变得更简单(但不太安全)。像这样的东西:
let property<'a, 'r> (e:Expr<'a -> 'r>) (cfg:EntityInfo<'a>) =
if typeof<'r> = typeof<string> then
// ...
关于F# - 重载函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5745172/