Why is None represented as null?

廉价感情. 提交于 2019-11-28 09:56:27

Jack's answer seems good, but to expand a little bit, at the IL level the CLR provides a specific opcode for loading null values (ldnull) and efficient means of testing for them (ldnull followed by beq/bne.un/ceq/cgt.un). When JITted, these should be more efficient than dereferencing a Tag property and branching accordingly. While the per-call savings are probably small, option types are used frequently enough that the cumulative savings may be significant.

Of course, as you note there is a tradeoff: methods inherited from obj may throw null reference exceptions. This is one good reason to use string x/hash x/x=y instead of x.ToString()/x.GetHashCode()/x.Equals(y) when dealing with F# values. Sadly, there is no (possible) equivalent of x.GetType() for values represented by null.

The F# compiler sometimes uses null as a representation for None because it's more efficient than actually creating an instance of FSharpOption<'T> and checking the Tag property.

Think about it -- if you have a normal F# type (like a record) that's not allowed to be null, then any pointer to an instance of that type (the pointer used internally by the CLR) will never be NULL. At the same time, if T is a type which can represent n states, then T option can represent n+1 states. So, using null as a representation for None simply takes advantage of that one extra state value which is available by the fact that F# types aren't allow to be null.

If you want to try turning this behavior off (for normal F# types), you can apply [<AllowNullLiteral(true)>] to them.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!