3

FirstOrDefault()以下のコードは、メソッド内で NullReferenceException をスローします。

open System
open System.Collections.Generic
open System.Linq

[<EntryPoint>]
let main argv = 
    let suspects = seq {
        yield ("Frank", 1.0)
        yield ("Suzie", 0.9)
        yield ("John", 0.5)
        // yield ("Keyser Soze", 0.3)
    }
    let likely = suspects.FirstOrDefault(fun (name, confidence) -> name = "Keyser Soze")
    printfn "Name: %s" (fst likely)
    Console.ReadLine() |> ignore
    0

それを回避する最善の方法は何ですか?それをキャッチするのは間違っているようです。イテレータを手動で取得して while ループに入れることもできますが、それは非常に多くのレベルで間違っています。

[編集] C# で行うこと、つまり、結果が null かデフォルトかを確認することさえできません。その理由は 2 つあります: (1)FirstOrDefault()結果を参照するときではなく、メソッドでエラーがスローされる; (2) null をチェックしようとすると、コンパイラは「型 '(string * float)' には適切な値として 'null' がありません」と不平を言います:

    if likely = null then            
        printfn "Nothing to see here"

助言がありますか?

4

2 に答える 2

2

上記のように、Seq.tryFindそれを達成するための慣用的な方法です。本当に使用FirstOrDefault()する必要がある場合は、次のようにすることができます。

open System.Collections.Generic
open System.Linq
let suspects = seq {
    yield Some("Frank", 1.0)
    yield Some("Suzie", 0.9)
    yield Some("John", 0.5)
    // yield ("Keyser Soze", 0.3)
}
let likely = suspects.FirstOrDefault(fun x -> let name, confidence = x.Value
                                              name = "Keyser Soze")
match likely with
| Some(x) -> printfn "Name: %s" (fst x)
| None -> printfn "Not Found"
于 2013-07-12T17:20:38.313 に答える
0

必要に応じて、ハードコードの null チェックで汚染された C# の方法に従うことができます。

...
let likely = suspects.FirstOrDefault(fun x -> x.Equals(null) || (fst x) = "Keyser Soze")
if obj.ReferenceEquals(likely, null) then
    printfn "Nothing to print"
else
    printfn "Name: %s" (fst x)
...

しかし、これは null チェックを完全に回避するという主要な F# イディオムに反しています。

編集:NullReferenceExceptionコメントで積極的に言及されているという主張は、FirstOrDefault単に起こらないようです! 上記のコードの最初の行を元に戻す

let likely = suspects.FirstOrDefault(fun (name, confidence) -> name = "Keyser Soze")

このスニペットは、最初の 3 つのタプルのシーケンスに対して問題なく機能します。

于 2013-07-12T18:11:14.110 に答える