类型没有 null 作为适当的值 [英] Type does not have null as a proper value
问题描述
对于示例程序:
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屋!