对于示例程序:
type public MyClass(reasonForLiving:string) =
member x.ReasonForLiving with get() = reasonForLiving
let classFactory () = MyClass("up to you")
let live () =
let instance = classFactory()
if instance = null then raise(System.Exception("null is not living... that's why OO languages die from bugs"))
instance
当我将此类用作隐式类型函数的返回值并将其与null进行比较时,出现错误“'MyClass' 类型没有 null 作为正确的值” (b/c 与 C# 依赖注入的兼容性要求我不能依赖 F# 选项类型)。
我可以通过将空检查更改为:
if instance :> obj = null then
但是,我知道(“感觉”)这完全是“错误的”。特别是当我考虑 MyClass 是一个不需要装箱的引用类型时(从 C# 背景说)。
我已经阅读了“F# 值限制”以及它如何影响类型推断,但我似乎无法看到它如何应用于这种场景。
问:还有其他方法可以做到这一点吗?
除了#1:我找到了一个更简单的方法来获取错误......
type public MyClass(reasonForLiving:string) =
member x.ReasonForLiving with get() = reasonForLiving
let nullMyClass : MyClass = null
除了#2:我确实尝试了 System.Nullable 没有考虑...... MyClass 是一个引用类型,而不是 Nullable<_> 需要的值类型(结构)。所以,只是让我放心,我真的在处理引用类型,让我想知道为什么对象强制转换突然使这项工作有效。
更新:对于任何感兴趣的人,我将其用作具有以下三个功能的 Common Service Locator 的一种解决方案。每个请求的服务都必须支持null,因此如果服务类是在 F# 中定义的,则需要添加[<AllowNullLiteral>]
:
let private getServiceLocator () =
try Some(Microsoft.Practices.ServiceLocation.ServiceLocator.Current)
with | _ -> None
let private getService serviceFactory =
let serviceLocator = getServiceLocator()
let service = match serviceLocator with
| None -> serviceFactory()
| _ ->
match serviceLocator.Value.GetInstance<'a>() with
| null -> serviceFactory()
| svc -> svc
match service with
| null -> None
| _ -> Some(service)
let private getRequiredService serviceFactory =
let service = getService serviceFactory
match service with
| None -> raise(MissingServiceException(""))
| _ -> service.Value