F# SingleOrDefault()在F中引发NullReferenceException#
下面的代码在F# SingleOrDefault()在F中引发NullReferenceException#,f#,F#,下面的代码在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 ("
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
有什么建议吗?如上所述,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"
如果您想:
...
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#习惯用法完全避免空检查背道而驰
EDIT:看来评论中主动引用的FirstOrDefault
中声称的NullReferenceException
似乎根本没有发生!将上面的第一行代码更改回原始代码
let likely = suspects.FirstOrDefault(fun (name, confidence) -> name = "Keyser Soze")
该代码段适用于前三个元组的序列,没有问题。是FirstOrDefault还是SingleOrDefault?请检查null,就像在C#(假设FirstOrDefault)…@Habib-中一样。行为方式相同。@ildjarn-无法检查null。如果您尝试,它将无法编译。异常在FirstOrDefault()
方法中抛出,而不是在随后引用结果时抛出。这是因为它返回的元组类型不能为null。您可以使用obj.ReferenceEquals
检查null,但无论如何,您确实应该使用Seq.tryFind
。关于将序列类型更改为Seq
的好提示。但在本例中,Seq.tryFind()
工作正常。谢谢。@KenSmith说得对。这只是对FirstOrDefault
进行黑客攻击的一种方法,因此它的工作原理与Seq.tryFind()
几乎相同。关于如何检查null,这是一个很好的方法。但是在我上面的例子中,它永远不会到达那一行,因为异常是在suspects.FirstOrDefault()
调用中抛出的。@KenSmith:在建议的解决方法suspects.FirstOrDefault()中
在没有搜索标准的情况下,在退出序列时不会抛出异常,因为它执行可怕的null
参数检查,并且不执行字符串比较(如果是这种情况)。我认为问题在于F#tuple类型没有默认值,这导致了FirstOrDefault()
在lambda传递给它的结果为false时引发异常。因此,在完成FirstOrDefault()
之后进行的任何检查都是不充分的。@mydogisbox:System.Tuple
是引用类型,因此与所有引用类型一样,其默认值为null
。在这种情况下,您不能使用=
或
检查null
。@ildjarn我指的是:let(tuple:int*int)=null
错误FS0043:(int*int)类型没有“null”作为正确的值,因为很可能是一个元组,F#不将null
识别为有效值。
let likely = suspects.FirstOrDefault(fun (name, confidence) -> name = "Keyser Soze")