12

ctor 引数でいくつかの検証を行う簡単な C# 構造体を次に示します。

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を見てきましたが、引数の検証はカバーしていません。

私はどこで間違っていますか?

4

2 に答える 2

12

then構造体を初期化した後にブロック を使用できます。セクションExecuting Side Effects in Constructorsの最初のリンクのクラスについて説明されていますが、構造体でも機能します。

[<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) } 
于 2012-09-26T11:49:17.180 に答える
7

val明示的なフィールド ( ) とthenの 2 つの比較的難解な機能を避けたい場合は、静的Createメソッドを使用して、より一般的な型定義構文に固執することができます。

[<Struct>]
type Foo private (name: string) = 
  member x.Name = name
  static member Create(name: string) =
    Contract.Requires<ArgumentException> (name.StartsWith "A")
    Foo(name)
于 2012-09-26T14:18:01.983 に答える