默认情况下F#中的引用是不可为空的吗?

Joa*_*nge 5 .net c# f# reference

我知道在C#中它不是,而且它是像Haskell这样的语言(如果我没有错),所以认为F#默认也有相同的语义.

即使它在C#中不存在,它也是语言的限制,而不是运行时,对吧?就像F#或其他一些新的.NET语言实际上可以将其作为默认值实现而不使用任何类型的hack.

Bri*_*ian 11

在F#中,如果在F#代码中定义新类或其他类型,则默认情况下它将是非可空的,在某种意义上,例如

type MyClass() = ...
...
let x : MyClass = null   // does not compile
Run Code Online (Sandbox Code Playgroud)

然而,它编译为.NET IL代码作为一个类,它是.NET上的引用类型,可以为null,因此C#可以创建该类型的空值,甚至在F#中

let x : MyClass = Unchecked.defaultOf<MyClass>
Run Code Online (Sandbox Code Playgroud)

会给你一个空的.所以在这个意义上,它非常"运行时的限制" - 你永远不能创建一个.NET语言,它既可以"将一个类暴露给C#,使它看起来像一个普通的类",也可以"确保实例那种类型永远不会为空".所以你总是要在这里做出务实的决定.当你留在F#中时,F#试图阻止你发生事故和处理null的烦恼,但是如果你处理interop或.NET运行时的细节,那么在一天结束时,null总是处于闲置状态.(十亿美元的错误.)


kvb*_*kvb 5

除了Brian提出的观点之外,值得一提的是,当您在F#中定义新类型时,null如果这是您想要的行为,您可以选择允许值.这是通过AllowNullLiteral属性完成的:

[<AllowNullLiteral>]
type T1() = class end

type T2() = class end

let t1 : T1 = null
let t2 : T2 = null // compiler error
Run Code Online (Sandbox Code Playgroud)

编辑

关于您的后续问题,是的,此属性适用于类型本身.绝大多数F#类型都不会应用此属性; 如果你有一个带有参数的函数或方法,你想允许它有一个有效的类型值或一个"类似null"的sentinel值,那么你可以使用一个option类型:

let myFunc (o:option<T2>) = 
  match o with
  | None -> "No value passed in"
  | Some(t2) -> "A T2 instance was passed in"
Run Code Online (Sandbox Code Playgroud)

选项类型类似于C#中的可空类型,除了它们不限于包装结构(以及与此主题无关​​的一些其他微小差异).