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

时间:2011-03-07 20:38:27

标签: c# .net f# reference

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

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

2 个答案:

答案 0 :(得分:11)

在F#中,如果你在F#代码中定义一个新类或其他类型,那么默认情况下它将是不可为空的,例如,

type MyClass() = ...
...
let x : MyClass = null   // does not compile

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

let x : MyClass = Unchecked.defaultOf<MyClass>

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

答案 1 :(得分:5)

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

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

type T2() = class end

let t1 : T1 = null
let t2 : T2 = null // compiler error

修改

关于您的后续问题,是的,此属性适用于类型本身。绝大多数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"

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