F#struct构造函数中的参数验证

时间:2012-09-26 11:21:36

标签: c# f# struct c#-to-f#

这是一个简单的C#结构,它对ctor参数进行了一些验证:

public struct Foo
{
    public string Name { get; private set; }

    public Foo(string name)
        : this()
    {
        Contract.Requires<ArgumentException>(name.StartsWith("A"));
        Name = name;
    }
}

我已设法将其转换为F#类:

type Foo(name : string) = 
    do 
        Contract.Requires<ArgumentException> (name.StartsWith "A")
    member x.Name = name

但是,我无法将其转换为F#中的结构:

[<Struct>]
type Foo = 
    val Name : string
    new(name : string) = { do Contract.Requires<ArgumentException> (name.StartsWith "A"); Name = name }

这会产生编译错误:

  

无效的记录,序列或计算表达式。序列表达式应为   形式'seq {...}'

     

这不是有效的对象构造表达式。显式对象构造函数必须   要么调用备用构造函数,要么初始化对象的所有字段并指定   调用超类构造函数。

我查看了thisthis,但它们不包括参数验证。

我在哪里做错了?

2 个答案:

答案 0 :(得分:12)

初始化结构后,可以使用then块。对于您在在构造函数中执行副作用中的第一个link中的类进行了描述,但它也适用于结构。

[<Struct>]
type Foo = 
    val Name : string
    new(name : string) = { Name = name } 
                         then if name.StartsWith("A") then failwith "Haiz"

<强>更新

更接近你的例子的另一种方法是使用;(顺序组合)和括号来组合表达式:

[<Struct>]
type Foo = 
    val Name : string
    new(name : string) = 
        { Name = ((if name.StartsWith("A") then failwith "Haiz"); name) } 

答案 1 :(得分:7)

如果您想避免显式字段(val)和then这两个相对深奥的功能,您可以使用静态Create方法并坚持更常见的类型定义语法:

[<Struct>]
type Foo private (name: string) = 
  member x.Name = name
  static member Create(name: string) =
    Contract.Requires<ArgumentException> (name.StartsWith "A")
    Foo(name)