2017-03-03 43 views
3

我实现一个模仿System.Data.Common.DbParameter类的类型。这种类型将用于C#,VB.NET和F#项目。这里是一个精简下来例如:F#:使用DU限制类型的物业

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

在类的Value属性是对象的类型。在我的类型中,我想限制该属性为字符串或字节数组。我认为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 

有人可以帮我的语法吗?在此先感谢

回答

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语法总是让我起来。最难的部分是弄清楚一个很好的默认值。我会说空字节数组在这里根本不理想,也许需要一个构造函数参数来设置初始状态应该是什么?

4

当您使用DU你必须明确地阐明你想使用

尝试像凡Initial将被用来作为一种的下方

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 

替代品默认。

3

缩写“DU”代表“的歧视性联盟”。也就是说,这是一个类型的工会,可以在其中区分它们之间。 “歧视”部分在这里很重要。这意味着联合中的每种类型都使用特殊标签“标记”,并且可以使用这些标签来确定它是哪种类型。

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#没有这些。

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组件设计指南将会很有帮助。