Mik*_*icz 1 null f# nullreferenceexception
当我单步执行以下代码时,report第二行为null.但是,第三行生成NullReferenceException.
member this.setTaggedResearchReportList (index : int) (taggedResearchReport : TaggedResearchReportUIVO option) =
let report = Option.get(taggedResearchReport)
if not(report.Equals(null)) then
// do some stuff here
Run Code Online (Sandbox Code Playgroud)
为什么会这样,我该怎么做才能避免呢?谢谢!
这是调用的行this.setTaggedResearchReportList:
getMostRecentTaggedResearchReportForSecurityId (item.id) (new Action<_>(this.setTaggedResearchReportList 0))
Run Code Online (Sandbox Code Playgroud)
这是getMostRecentTaggedResearchReportForSecurityId方法:
let getMostRecentTaggedResearchReportForSecurityId (securityId : int) (callbackUI : Action<_>) =
getSingleRPCResult<JSONSingleResult<TaggedResearchReportUIVO>, TaggedResearchReportUIVO>
"TaggedResearchReportRPC"
"getMostRecentResearchReportForSecurityId"
(sprintf "%i" securityId)
callbackUI
(fun (x : option<JSONSingleResult<TaggedResearchReportUIVO>>) ->
match x.IsSome with
| true -> Some(Option.get(x).result)
| false -> None
)
Run Code Online (Sandbox Code Playgroud)
这本身不是答案,而是添加到空处理的讨论中,特别是在与C#代码交互时:我喜欢避免使用该[<AllowNullLiteral>]属性并定义如下的模块来隔离nullF#中的使用码.
[<AutoOpen>]
module Interop =
let inline isNull value = System.Object.ReferenceEquals(value, null)
let inline nil<'T> = Unchecked.defaultof<'T>
let inline safeUnbox value = if isNull value then nil else unbox value
let (|Null|_|) value = if isNull value then Some() else None
type Foo() = class end
type Test() =
member this.AcceptFoo(foo:Foo) = //passed from C#
if isNull foo then nullArg "foo"
else ...
member this.AcceptFoo2(foo:Foo) = //passed from C#
match foo with
| Null -> nullArg "foo"
| _ -> ...
member this.AcceptBoxedFoo(boxedFoo:obj) =
let foo : Foo = safeUnbox boxedFoo
...
member this.ReturnFoo() : Foo = //returning to C#
if (test) then new Foo()
else nil
Run Code Online (Sandbox Code Playgroud)
通常,将这些检查尽可能地靠近API的接口,并且null由于保留了编译器的空检查,您通常可以忘记在F#中.