类型没有 null 作为适当的值 [英] Type does not have null as a proper value

查看:18
本文介绍了类型没有 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 作为正确值"(与 C# 依赖注入的兼容性要求的 b/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).

我可以通过将空检查更改为:

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#中定义的,则需要添加[]:

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

推荐答案

使用 [] 属性:

Use the [<AllowNullLiteral>] attribute:

[<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天全站免登陆