我具有以下带有成员函数的已区分联合,要在其中返回未装箱的类型:
type ModelData =
| Double of double
| UInt32 of uint32
| UInt16 of uint16
| Byte of byte
| Int32 of int32
| String of string
| Bit of Bit
member inline this.Value : 'a =
match this with
| Double x -> x
| UInt32 x -> x
| UInt16 x -> x
| Byte x -> x
| Int32 x -> x
| String x -> x
| Bit x -> x
错误是成员'this.Value'没有为每个分支返回相同的类型。这可能吗?
编辑#1
我有一个如下定义的数据库,它使用这种ModelData
类型:
module Database =
type Drecord =
{ Value: ModelData}
type Db = Dictionary<string, Drecord>
所以我有一个充满值的数据库,然后使用其中一些值并使用sprintf生成JSON字符串。
sprintf "{\"General\":{\"Example\":%.3f}}" value //where value is of type ModelData
这当前不起作用,因为sprintf需要float
而不是ModelData
。所以原来我以为我可以调用一个函数以安全地转换为该类型(因此,this.Value
成员)。我通过让this.Value
代替返回一个字符串,并且在我的sprintf格式字符串中只有%s
来解决这个问题。
如此有效:
sprintf "{\"General\":{\"Example\":%s}}" value.Value
是否有更好的方法来解决这个问题?
答案 0 :(得分:2)
我不确定我了解您要做什么。如果定义了一个有区别的联合,则该值可以是两种情况之一,并且当您要使用ModelData
类型的值时,需要对其进行模式匹配以确定哪种值你有。
如果您添加一种获取仅在特定情况下有效的值的方式(例如,当该值是float
时),您将失去已区别工会提供的所有安全性。因此,我认为按照您的要求去做很可能不是一个好主意。
也就是说,您可以定义一个成员GetValue<'a>
,可以使用unbox
函数来调用该成员以提取特定类型的值:
type ModelData =
| Double of double
| UInt32 of uint32
| UInt16 of uint16
member inline this.GetValue<'a>() : 'a =
match this with
| Double x -> unbox<'a> x
| UInt32 x -> unbox<'a> x
| UInt16 x -> unbox<'a> x
let v = Double 1.23
v.GetValue<float>()
如果您使用错误的类型参数(例如,在上述情况下为InvalidCastException
。另外请注意,这必须是一种方法,以便您可以使其通用。