这是一个简单的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 {...}'
这不是有效的对象构造表达式。显式对象构造函数必须 要么调用备用构造函数,要么初始化对象的所有字段并指定 调用超类构造函数。
我在哪里做错了?
答案 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)