4

リアクティブ拡張機能を使用した次のコードスニペットがあります。

    let value : 't = ...

    Observable.Create<'t>(fun observer ->
        let subject = new BehaviorSubject<'t>(value)
        let d0 = subject.Subscribe(observer)
        let d1 = observable.Subscribe(subject)
        new CompositeDisposable(d0, d1) :> IDisposable
    )

これは機能します。ただし、アップキャストをIDisposableにドロップすると、あいまいなオーバーロードが原因で、コードのコンパイルに失敗します。ただし、CompositeDisposableはIDisposableです。型推論エンジンがこれを解決できないのはなぜですか?このパターンは、C#でほぼ常に使用しており、アップキャストせずにObservable.CreateからCompositeDisposableを返します。

4

1 に答える 1

8

@kvbが言ったように、関数はバリアンスをサポートしていないため、インターフェイスとサブクラスにはアップキャストが必要です。

サブクラスでの動作を示す小さな例を次に示します。

type A() =
    member x.A = "A"

type B() =
    inherit A()
    member x.B = "B"

let f (g: _ -> A) = g()

let a = f (fun () -> A()) // works
let b = f (fun () -> B()) // fails

関数fがあなたによって書かれている場合、型の制約を追加すると役立つ場合があります。

// This works for interface as well
let f (g: _ -> #A) = g()

let a = f (fun () -> A()) // works
let b = f (fun () -> B()) // works

それ以外の場合は、例で説明したように少しアップキャストする必要があります。

于 2012-12-21T07:23:46.073 に答える