首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >列表上的Unchecked.defaultof

列表上的Unchecked.defaultof
EN

Stack Overflow用户
提问于 2012-11-23 06:18:42
回答 1查看 1.5K关注 0票数 25

考虑一下:

代码语言:javascript
复制
> Unchecked.defaultof<list<int>>;;
val it : int list = null
> 2 :: 1 :: Unchecked.defaultof<list<int>>;;
val it : int list = [2]

这种行为背后的原因是什么?我希望最终的列表是2;1,或者引发一个异常。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-11-23 09:01:27

这是一个非常令人惊讶的问题。我研究了F#列表是如何编译的,它解释了这种行为。我不会认为这是错误(这就是为什么defaultofUnchecked模块中,它可能会烧毁您的计算机!)

首先,在F# 2.0中,空列表[]没有表示为null,因为这样就不能调用空列表上的方法了--这会破坏很多东西(比如将空列表传递给任何Seq函数)。另外,为了提高效率,None值被表示为null,这意味着option<'a>不能实现seq<'a>接口,即使它是有意义的。

因此,F#使用一个特殊的值list.Empty来表示空列表。现在这个值是与表示非空列表的值具有相同类型的实例(类型为FSharpList<'T>)。唯一的区别是实例的headtail字段都是null

现在,您也许可以看到这是怎么回事了--一个空列表实际上被编译成一个对象,其中的this.tail字段为null ( this.head字段也为null,但这并不重要)。

当字段this.tailnull时,list.Tail属性将抛出异常(因为这意味着您将获得一个空列表的尾部--这是一个错误),但是还有一个内部属性list.TailOrNull,它返回不进行检查的值,并用于编译模式匹配。

例如,下面是一个简单的iter函数:

代码语言:javascript
复制
let rec iter (xs:int list) = 
  match list with
  | x::xs -> Console.WriteLine(x); iter xs
  | [] -> ()

这将被编译为以下C#代码:

代码语言:javascript
复制
if (list.TailOrNull != null) {
  Console.WriteLine(list.HeadOrDefault);
  iter(list.TailOrNull);
}

这将通过检查其list.TailOrNull是否为null来检查list是否为空列表。如果是,那么它知道当前的list值是表示空列表的list.Empty值(并且它不打印它的HeadOrDefault,因为它假定这也是null )。

如果您使用defaultof显式地创建null值,那么42::null将提供一个对象,其中TailOrNullnull,而HeadOrDefault42。这就是为什么不打印这个值的原因。

TL;DR -不要将Unchecked.defaultof与F#类型一起使用。你永远不会知道会发生什么。

票数 29
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13520720

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档