2011-07-12 14 views
2

投稿によるとhttp://cs.hubfs.net/forums/thread/3616.aspx、 私はインターフェイスにオブジェクトをキャストするために、私はテストを実行しました、これはまだtrueのバグ:?>はまだです未修理。インターフェイスへの動的キャスト

let cast<'a> o = (box o) :?> 'a 
let ci = { new Customer(18, Name = "fred") with 
       override x.ToString() = x.Name 
      interface ITalk with 
       member x.Talk() = 
        printfn "talk1111111" } 

let italk = cast<ITalk> ci 

if not (italk = null) then 
    italk.Talk() 

上記のコードを書くには、よりエレガントな方法がありますか? ?>のように渡されるジェネリック型パラメータを取得できません:?>

答えて

6

cast関数はC#asのように動作しません演算子 - 指定した型にキャストすると、nullを返すのではなく例外がスローされます。したがって、italk = nullが何も成就していないかどうかを確認してください。あなたはcast関数の戻りヌルを作りたい場合はキャストが例外をスローするのではなく、失敗した場合、あなたはこのようにそれを書くことができます:

let cast<'a when 'a : null> o = 
    match box o with 
    | :? 'a as output -> output 
    | _ -> null 

しかし、これが唯一の構造体が含まれたりしない、NULL可能なタイプで動作します(デフォルトでは)F#タイプです。私はあなたのcast機能をそのままにして、オプションを使用するtryCastを作るかもしれません。

let tryCast<'a> o = 
    match box o with 
    | :? 'a as output -> Some output 
    | _ -> None 

その後、あなたはこのようにそれを使用することができます。

ci |> tryCast<ITalk> |> Option.iter (fun it -> it.Talk()) 

をこの場合、Option.iterはあなたのヌルテストの行われます。

+0

私はオペレータを作成し、O以下 letのような=(ボックスO):?>「 ましょうITX:ITalk => CI itx.Talk() が、そこの欠点は、識別子の注釈として入力する、とするようなタイプは何があるということではありません!コンパイル時のチェック –

2

パターンマッチングがこれを書くためのより多くの慣用的な方法を提供します:

match box ci with 
| :? ITalk as italk -> italk.Talk() 
| _ ->() 

か、さえ:

let bci = box ci 
if bci :? ITalk then (bci :?> ITalk).Talk() 

私は型テスト意志を知っているとき、私は周りに次のような機能を維持し、ためホールド: "!>"(!>)

let coerce value = (box >> unbox) value 

(coerce ci : ITalk).Talk() 
+0

はコンパイルできません。 –

+0

@Fred:申し訳ありませんが、ブラウザに入力してください。オブジェクト式は最初に実装された型に従って型付けされているので、 'box'を呼び出す必要があります。私はコードを修正した。 – Daniel

+0

@Fred:あなたのケースでうまくいく別のオプションで私の答えを更新しました。 – Daniel

関連する問題