F#:使用DU限制属性

时间:2017-03-03 14:56:13

标签: .net f#

我正在实现一个模仿System.Data.Common.DbParameter类的类型。此类型将用于C#,VB.NET和F#项目。这是一个精简的例子:

type myNewType =
   member val Direction: int = 0 with get,set
   member val Value: Object = null with get,set

类中的Value属性是object类型。在我的类型中,我想将该属性限制为字符串或字节数组。我认为DU可能是完美的,但我不确定语法。这是一些psudo代码:

type Value =
| Value of String or byte[]

type myNewType =
   member val Direction: int = 0 with get,set
   member val Value: Value = [||] with get,set

有人可以帮我解释语法吗?提前致谢

4 个答案:

答案 0 :(得分:5)

type DbParameterValue = 
| StringValue of s: string
| BytesValue of bytes: byte[]

type myNewType() = 
  member val Direction = 0 with get, set
  member val Value: DbParameterValue = BytesValue([||]) with get, set

成员val语法总是让我兴奋。最困难的部分是找出一个好的默认值。我说这里的空字节数组并不理想,或许可以用构造函数参数来设置初始状态应该是什么?

答案 1 :(得分:4)

当您使用DU时,您必须明确说明您想要使用的替代方案

尝试类似下面的内容

type Value =
| StringVal of string
| ByteVal of byte[]
| Initial

type myNewType =
    member val Direction: int = 0 with get,set
    member val Value: Value = Initial with get,set

Initial将被用作某种默认值。

答案 2 :(得分:4)

从F#的角度来看,您似乎可以通过使用两个判别联盟来建模您的域名,一个用于方向,一个用于值。

type Direction =
    |Input
    |InputOutput
    |Output
    |ReturnValue

type Value =
    |String of string
    |Bytes of byte[]

然后将它们合并到DBParameter类型中。我建议为此记录语法:

type DBParameter = {Direction : Direction; Value : Value}

然后你可以创建一个这样的实例:

let dbParam = {Direction = ReturnValue; Value = String "Some return value"}

您需要考虑如何在其他.NET语言中使用受歧视的联合。为此,参考section 5.1组件设计指南会很有帮助。

答案 3 :(得分:3)

首字母缩略词" DU"代表"被歧视的联盟"。也就是说,它是一种类型的联合体,您可以在它们之间区分。 " 歧视"部分在这里很重要。这意味着联盟中的每种类型都被标记为#34;使用特殊标签,您可以使用这些标签来判断它是什么类型。

type Value = StringValue of string | ByteValue of byte[]

要创建此类型的值,请指定您的意思:

let v1 = StringValue "abc"
let v2 = ByteValue [|1b;2b;3b|]

当您从某处获得值时,您可以使用标签来确定您获得的值:

match v with
| StringValue s -> printfn "Got a string: %s" s
| ByteValue a -> printfn "Got %d bytes" a.Length

有些语言有"不加区分的工会"。例如,在TypeScript中,您可以这样做:

type T = string | number;
var x : T = 5;
x = "abc"
if ( typeof x === "string" ) return x.length;

F#没有那些。