首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >枚举器及其在F#中的处理

枚举器及其在F#中的处理
EN

Stack Overflow用户
提问于 2012-11-22 12:13:38
回答 1查看 1.4K关注 0票数 4

我正试图从我简化的一个例子中吸取以下行为的教训:

代码语言:javascript
复制
let groupedEnum  (input: 'a seq) =
   using (input.GetEnumerator()) (fun en ->
   Seq.unfold(fun _ -> 
                  if en.MoveNext() then 
                     Some(en.Current, ())
                  else None) ()
   )


//WORKS    
let c = groupedEnum    ("11111122334569999"   |>  List.ofSeq ) |>  List.ofSeq 

//BOOM !!  System.NullReferenceException
let c = groupedEnum    ("11111122334569999"                  ) |>  List.ofSeq
  • 枚举数"en“是否在被捕获的情况下被独立处理?(我想是的,但除了重源上的msdn文档之外,还有什么可供阅读的吗?)
  • 如果先将序列转换为列表,为什么要工作呢?

编辑:,这只是一个玩具例子,用来说明一种行为,而不是被遵循。很少有充分的理由直接操作枚举器。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-11-22 12:35:05

一旦lambda函数返回,using函数就会处理枚举数。但是,lambda函数使用Seq.unfold创建一个延迟序列,在从groupedEnum返回序列之后,延迟序列访问枚举数。

您可以完全评估using内部的整个序列(通过在其中添加List.ofSeq ),也可以在到达生成序列的末尾时调用Dispose

代码语言:javascript
复制
let groupedEnum  (input: 'a seq) =
   let en = input.GetEnumerator()
   Seq.unfold(fun _ -> 
       if en.MoveNext() then 
           Some(en.Current, ())
       else 
           en.Dispose()
           None)

在这种情况下,异常处理变得非常困难,但我想其中一种方法是将主体封装在try .. with中,并在发生异常时调用Dispose (然后返回None)。

如果您使用序列表达式,那么use的含义就会发生变化,并且它会在到达序列结束后(而不是在返回延迟序列时)自动处理枚举数。因此,使用序列表达式可能是一个更好的选择,因为辛苦的工作是为您完成的:

代码语言:javascript
复制
let groupedEnum  (input: 'a seq) = seq {
   use en = input.GetEnumerator()
   let rec loop () = seq {
      if en.MoveNext() then 
         yield en.Current
         yield! loop () }
   yield! loop () }

编辑,为什么它在您的第一个示例中工作?F#列表类型返回的枚举数简单地忽略Dispose并继续工作,而如果对由string返回的枚举数调用Dispose,则不能再次使用该枚举数。(这可以说是F#列表类型的一些奇怪行为。)

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

https://stackoverflow.com/questions/13512519

复制
相关文章

相似问题

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