类型不包含null作为适当值 [英] Type does not have null as a proper value

查看:69
本文介绍了类型不包含null作为适当值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于示例程序:

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#选项类型.

I get the error "The type 'MyClass' does not have null as a proper value" when I go to use this class as a return value of implicitly typed functions and compare it to null (b/c of compatibility requirements with C# dependency injection I cannot rely on F# option types).

我可以通过将null检查更改为以下内容来轻松解决此问题:

I can easily fix this by changing the null check to:

if instance :> obj = null then

但是,我知道(感觉")这完全是错误的".尤其是当我考虑MyClass如何成为不需要装箱的引用类型时(从C#背景来讲).

However, I know ("feel") this is completely "wrong". Especially when I consider how MyClass is a reference type that shouldn't need to be boxed (speaking from a C# background).

我已经阅读了有关"F#值限制"及其对类型推断的影响的信息,但我似乎看不到它如何应用于这种情况.

I've read about "F# Value Restriction" and how it impacts type inference, but I can't seem to gleam how it applies to this scenario.

问:还有另一种方法吗?

除了#1:我发现了一种更简单的获取错误信息的方法...

Aside #1: I found a simpler method of getting the error...

type public MyClass(reasonForLiving:string) =
    member x.ReasonForLiving with get() = reasonForLiving
let nullMyClass : MyClass = null

除了#2:我没有想到就尝试了System.Nullable ... MyClass是引用类型,而不是Nullable< _>所需的值类型(结构).因此,只是向我保证我真的在处理引用类型,而让我想知道为什么对象强制转换会导致这项工作.

Aside #2: I did try System.Nullable without thinking... MyClass is a reference type and not a value type (struct) which Nullable<_> requires. So, just reassures me that I REALLY am dealing with a reference type and leaves me wondering why an object cast suddenly makes this work.

更新:对于感兴趣的任何人,我将其用作具有以下三个功能的Common Service Locator的一种解决方案.请求的每个服务都必须支持 null ,因此,如果服务类在F#中定义,则需要添加[<AllowNullLiteral>]:

Update: For anyone interested, I used this as one solution for Common Service Locator with the three functions below. Each service requested must support null, so if the service class is defined in F#, you need to add the [<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

推荐答案

使用 [<AllowNullLiteral>] 属性:

[<AllowNullLiteral>]
type public MyClass(reasonForLiving:string) =
    member x.ReasonForLiving with get() = reasonForLiving

默认情况下,F#类型不允许为null(谢谢!).此属性对于与其他.NET语言互操作很有用,并且允许赋值/比较为null.

By default, F# types do not allow null (thank heavens!). This attribute is useful for interop with other .NET languages and allows assignment/comparison with null.

这篇关于类型不包含null作为适当值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆