我可以在对象表达式中使用'use'关键字吗?

时间:2011-04-26 11:40:06

标签: f#

我正在使用对象表达式来实现两个接口。其中一个接口是IDisposable。我希望能够将'use'关键字与此对象表达式的结果一起使用,但是我收到错误:

  

类型约束不匹配。类型   IConnMan与类型不兼容   IDisposable“IConnMan”类型不是   兼容类型   'IDisposable的'

为什么会出现此错误?

let connectionstring = "context connection=true"
let connman () = 
   let conn = new SqlConnection(connectionstring)
   conn.Open()
   { new IConnMan with
        member x.Connect () = conn
        member x.Disconnect c = ()
     interface IDisposable with
        member x.Dispose() = 
           conn.Close()
           conn.Dispose()
   }

 ... 

 let f() = 
    use cn = connman() // <-- Error!

2 个答案:

答案 0 :(得分:4)

对象表达式只能有一种类型。类型是第一个(主要)实现的接口的类型 - 在您的情况下,这是IconnMan类型。 F#不允许您使用use,因为它不会静态地知道connman函数的结果是IDisposable

您可以按相反的顺序在对象表达式中创建接口:

let connman () = 
  let conn = new SqlConnection(connectionstring)
  conn.Open()
  { new IDisposable with
      member x.Dispose() = 
          conn.Close()
          conn.Dispose()
    interface IConnMan with
      member x.Connect () = conn
      member x.Disconnect c = () }

然后你可以写use cn = connman()但是你不能在没有强制转换的情况下使用IConnMan的函数(这与Desco所做的基本相同)。我不认为这个问题有任何好的解决方案。

您的IConnMan界面是否可以继承IDisposable

答案 1 :(得分:3)

F#规范说:

对象表达式的静态检查如下。 首先,检查ty0到tyn,并且必须都是命名类型。表达式的整体类型是ty0,并且声明等于表达式的初始类型。但是,如果ty0的类型与System.Object等效,并且存在ty1,则整体类型为ty1。

因此您可以使用类型测试和向下转换或更改正在实现的接口序列,因此IDisposable将是第一个

let f() = 
    use cn = connman() :?> IDisposable