7

次のコードがあります。

public abstract class A ...
public class B : A ...
public class C : A ...

void my_fct(A x) {
  if (x is B) { block_1 }
  else if (x is C) { block_2 }
  else { block_3 }
}

F# からの良い翻訳なのだろうか

type a = B | C
let my_fct x =
  match x with
  | B -> ( block_1 )
  | C -> ( block_2 )
  | _ -> ( block_3 )

??

4

2 に答える 2

13

F# 判別共用体は OO クラス階層に非常に密接に対応するため、おそらくこれが最適なオプションです。最も顕著な違いは、型宣言を変更しないと判別共用体に新しいケースを追加できないことです。一方、その型で動作する新しい関数を簡単に追加できます (これは、C# で新しい仮想メソッドを追加することにほぼ相当します)。

したがって、新しい継承クラス (ケース) を追加する予定がない場合は、これが最適なオプションです。それ以外の場合は、F# オブジェクト型 (またはシナリオによっては他のオプション) を使用できます。

コードに関するもう 1 つのポイント - 新しいケースを追加できないため、F# コンパイラは、必要なケースは と だけであることを認識していBますC。その結果、block_3を実行することはできません。つまり、次のように記述できます。

let my_fct x = 
  match x with 
  | B -> ( block_1 ) 
  | C -> ( block_2 ) 
于 2011-09-07T12:44:01.540 に答える
8

はい、これは多かれ少なかれ F# と同じです。この場合 (値は追加されません) - F# はこれを "a" といくつかのタグ (列挙型) のクラスに変換するようです。"a" のクラスには、B と C のいくつかの静的プロパティと、"a" 型のオブジェクトが "B" か "C" かをチェックするいくつかのメソッドがあります (以下を参照)。

タイプの Object-Browser

ただし、「_ -> (block_3)」のケースは必要ありません。これは決して一致しないためです (F# は考えられるすべてのケースを認識しており、警告を表示します)。

この「else」の場合は、C# で例外をスローした方がよいと思います。

于 2011-09-07T12:44:38.107 に答える