【问题标题】:Argument validation in F# struct constructorF# struct 构造函数中的参数验证
【发布时间】:2012-09-18 00:15:35
【问题描述】:

这是一个简单的 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,但它们不包括参数验证。

我哪里做错了?

【问题讨论】:

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


    【解决方案1】:

    您可以在初始化结构后使用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) } 
    

    【讨论】:

    • 啊,我试过在 {} 中使用 then。当这不起作用时,我认为这是因为它只能在类构造函数中使用(如链接文章该部分中所建议的那样)。当您说“不完全一样”时,是因为验证是在分配之后进行的吗?
    • 是的,对象在抛出异常之前就已经构建好了。
    • 我通过在 try/catch 中调用 foo = new Foo("A") 然后检查了 catch 块中的 foo 实例,从 C# 测试了您的示例。我希望 foo.Name 等于“A”,但它为空,即该对象尚未构造。在这种情况下,您的解决方案 等同于 C# 代码。
    • 太好了,感谢您提供的信息。我相应地更新了答案。
    【解决方案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)
    

    【讨论】:

    • 很高兴了解该选项 - 我没有意识到您可以使用与类相同的语法定义结构(除了 [])。但是,我不太喜欢 Create 方法——我更喜欢简单的 ctor,所以会坚持学习 val 然后。
    猜你喜欢
    • 1970-01-01
    • 2022-06-18
    • 2010-12-27
    • 1970-01-01
    • 2013-02-17
    • 2019-04-02
    • 1970-01-01
    • 1970-01-01
    • 2018-08-26
    相关资源
    最近更新 更多