我正在用F#编写一个库,其中一些接口和基类是公开可见的.一般情况下,我避免指定[<AllowNullLiteral>]我的自定义类型,因为这在我的F#代码验证逻辑(见复杂的F#这个不错的职位对商品和空移交的劣品得到的图片),而且,F#最初不容许null的F#类型.因此,我仅对接受该null值为有效的类型验证null .
但是,当我的库使用其他.NET语言(例如C#)时会出现问题.更具体地说,我担心在C#代码调用时,我应该如何实现接受F#-declared接口的方法.接口类型在C#中可以为空,我怀疑C#代码传递null给我的F#方法不会有问题.
我担心调用者会因NPE而崩溃和烧毁,问题是我甚至不允许在F#代码中正确处理它 - 比如抛出ArgumentNullException- 因为相应的接口缺少AllowNullLiteral属性.我担心我必须使用该属性并在我的F#代码中添加相关的空检查逻辑,以最终防止这种灾难.
我的恐惧是否合理?我有点困惑,因为我最初试图坚持良好的F#做法并null尽可能避免.如果我的目标之一是允许C#代码继承并实现我在F#中创建的接口,这会如何改变?如果它们是公共的并且可以从任何CLR语言访问,我是否必须允许来自我的F#代码的所有非值类型的空值?是否有最佳实践或良好建议?
当我单步执行以下代码时,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)