1

次のコードは、 の呼び出しでSqlDataReaderfromの戻り値をgetReader正しくキャストしていません。私は何を間違っていますか?IDataReaderSeq.unfold

open System.Data
open System.Data.SqlClient
open System.Configuration

type Foo = { id:int; name:string }

let populateFoo (r:IDataReader) =
    let o = r.GetOrdinal
    { id = o "id" |> r.GetInt32; name = o "name" |> r.GetString; }

let iter populateObject (r:IDataReader)  =
    match r.Read() with
    | true -> Some(populateObject r, r)
    | _    -> None

let iterFoo = iter populateFoo

let getReader : IDataReader =
    let cnstr = ConfigurationManager.ConnectionStrings.["db"].ConnectionString
    let cn = new SqlConnection(cnstr)
    let cmd = new SqlCommand("select * from Foo", cn)
    cmd.ExecuteReader()

let foos = Seq.unfold iterFoo getReader
4

1 に答える 1

3

F# は、いくつかの特定のシナリオを除いて、C# のように自動アップキャストしません (仕様のセクション 14.4.2 を参照してください)。

式を明示的にキャストする必要があります。cmd.ExecuteReader() :> IDataReaderその後、型注釈を削除できますgetReader

SqlDataReaderまたは、呼び出しサイトで と アップキャストを返す関数をそのままにしておくこともできます。

let foos = getReader :> IDataReader |> Seq.unfold iterFoo

unfold次のような署名を持つ型の静的メンバーだった場合:

type T() =
    static member unfold(a, b:IDataReader) = Seq.unfold a b

直接行うことができ、T.unfold(iterFoo, getReader)自動的にアップキャストされます。これは、仕様で言及されているケースの 1 つです。

于 2015-01-09T21:00:48.467 に答える