在F#结构构造函数的参数验证(Argument validation in F# struct co

2019-07-31 23:10发布

Here is a trivial C# struct that does some validation on the ctor argument:

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

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

I've managed to translate this into an F# class:

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

However, I can't translate this to a structure in F#:

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

This gives compile errors:

Invalid record, sequence or computation expression. Sequence expressions should be of the form 'seq { ... }'

This is not a valid object construction expression. Explicit object constructors must either call an alternate constructor or initialize all fields of the object and specify a call to a super class constructor.

I've had a look at this and this but they do not cover argument validation.

Where am I doing wrong?

Answer 1:

您可以使用then初始化结构后阻塞。 它的类在你的第一个描述链接的部分执行中构造的副作用 ,但它适用于结构为好。

[<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) } 


Answer 2:

如果你想避免明确的领域( 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)


文章来源: Argument validation in F# struct constructor