4

私がそうするならそれは意味がありません

type Point = 
    struct
        val Row: int
        val Column: int

        new (row, column) = if row >= 0 && column >= 0 then { Row = row; Column = column }
                            else failwith "Cooridinators must be non-negative!" 
        // This is not a valid object construction
        static member (+) (x: Point, y: Point) = Point (x.Row + y.Row, x.Column + y.Column)
        static member (-) (x: Point, y: Point) = Point (x.Row - y.Row, x.Column - y.Column)
        static member (*) (x: Point, a) = Point (x.Row * a, x.Column * a)
        static member (*) (a, x: Point) =  Point (x.Row * a, x.Column * a)
    end

それがクラスだった場合、doバインディング中に例外を発生させることができるかもしれませんが、構造にはありませんdo、私は何をすべきですか?

これを回避するために後で別のコンストラクターを追加することは可能であることがfailwithわかりましたが、別の質問が発生します。暗黙のコンストラクターをどのように呼び出すことができますか?最初に明示的に作成する必要がありますか

new () = { Row = 0; Column = 0} 
// Error structs auto supports a default constructor

デフォルトのコンストラクターを使用してこれを行うだけの場合

new (row, column) = if row >= 0 && column >= 0 then { Row = row; Column = column }
                    else
                        failwith "Cooridinators must be non-negative!"
                        new Point () // error

Point ()ではなくユニットを返すように見えます。Point

4

3 に答える 3

9

コンストラクターは常に構造を持つ必要があるため、F#コンパイラは文句を言うと思います。

new ( パターン ) = { 初期化 } [then ]

したがって、フィールドを初期化する部分は、if他の式の下または内部にネストすることはできません。初期化の前または後(thenキーワードを追加した場合)に例外をスローできます。(これは継承のあるクラスでは重要ですが、構造体では何の違いもないと思います。)

したがって、コードを記述する1つの方法は、次のように記述することです。

type Point = 
    struct
        val Row: int
        val Column: int

        new (row, column) = 
          if row < 0 || column < 0 then failwith "Cooridinators must be non-negative!"
          { Row = row; Column = column }          

        // (Static members omitted)
    end

(オブジェクトをいつ構築できるかを言うのではなく)例外をスローするときに大文字と小文字を指定する必要があるため、条件を否定する必要があることに注意してください。他の選択肢は次のとおりです。

new (row, column) = 
  { Row = row; Column = column }          
  then if row < 0 || column < 0 then failwith "Cooridinators must be non-negative!"
于 2013-01-16T00:45:12.213 に答える
4

初期化セクションで例外をスローする別の方法があります。

new (row, column) = 
  { Row = ((if row < 0 || column < 0 then failwith "Coordinators must be non-negative!"); row); 
    Column = column }

構造体コンストラクターを検証することは必ずしも良い考えではないことを覚えておいてください。ご存知のように、デフォルトのコンストラクターの初期化を制御することはできません。クラスの場合は、すべてのコンストラクターが希望する方法で検証されていることを確認できます。

于 2013-01-16T07:54:23.007 に答える
1

それは古い質問です。ただし、これについてはどの回答も言及されていません。慣用的なF#の方法は、例外をまったくスローしないことだと思います。これを実現するには、を使用できます。これは、すべての条件が満たされ、問題が発生した場合static member tryCreateに返されます。次に、オプションタイプの軌跡をたどって、例外を処理する代わりにロジックをコーディングします。また、非常に特定の目的のために構造体が明示的に必要でない限り、F#レコードもおそらくより慣用的な方法だと思います。 Some PointNone

于 2019-01-08T13:25:35.060 に答える