下面的代码在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或默认值,原因有两个:(1)FirstOrDefault()
方法中引发错误,而不是在引用时结果; (2)如果我尝试检查null,编译器会抱怨`'type'(string * float)'没有'null'作为正确的值':
if likely = null then
printfn "Nothing to see here"
有什么建议吗?
答案 0 :(得分: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"
答案 1 :(得分:0)
如果您想:
,可以按照硬编码空检查 - 污染的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)
...
但是这完全避免了空检查,这与主要的F#习惯相反。
编辑:在评论中主动提及的NullReferenceException
内的FirstOrDefault
似乎根本没有发生!上面的第一行代码更改回原来的
let likely = suspects.FirstOrDefault(fun (name, confidence) -> name = "Keyser Soze")
该代码段适用于三个第一元组的序列而没有问题。