对于示例程序:
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(b/c兼容性要求与C#依赖注入)进行比较时,我得到错误"类型'MyClass'没有null作为正确的值" 我不能依赖F#选项类型).
我可以通过将null检查更改为:
if instance :> obj = null then
但是,我知道("感觉")这完全是"错误的".特别是当我考虑MyClass如何是一个不需要盒装的引用类型时(从C#背景说起).
我已经读过"F#Value Restriction"以及它如何影响类型推断,但我似乎无法理解它如何应用于这种情况.
问:还有其他办法吗?
除了#1:我发现了一种更简单的方法来获取错误......
type public MyClass(reasonForLiving:string) =
    member x.ReasonForLiving with get() = reasonForLiving
let nullMyClass : MyClass = null
除了#2:我确实尝试过System.Nullable而不考虑... MyClass是一个引用类型,而不是Nullable <_>所需的值类型(struct).所以,只是向我保证,我真的在处理一个引用类型,让我想知道为什么一个对象突然使这个工作.
更新:对于任何感兴趣的人,我使用它作为公共服务定位器的一个解决方案,具有以下三个功能.请求的每个服务都必须支持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
Dan*_*iel 45
使用[<AllowNullLiteral>]属性:
[<AllowNullLiteral>]
type public MyClass(reasonForLiving:string) =
    member x.ReasonForLiving with get() = reasonForLiving
默认情况下,F#类型不允许null(谢天谢地!).此属性对于与其他.NET语言互操作很有用,并允许与null进行赋值/比较.
ild*_*arn 17
该AllowNullLiteral属性的问题在于,除了允许您将对象与null进行比较之外,还可以将对象设置为 null.
假设这不适合您的用例,有一个简单的替代方案,具有不可观察的性能影响:
let inline isNull (x:^T when ^T : not struct) = obj.ReferenceEquals (x, null)
然后,而不是做if instance = null then,if isNull instance then而是做.
这适用于任何引用类型(包括记录和DU),但不会引入将F#类型的对象设置为从F#中为空的可能性 - 两者中最好的.