I'm using an object expression to implement two interfaces. One of the interfaces is IDisposable. I expected to be able to use the 'use' keyword with the results from this object expression, but I get an error:
我正在使用一个对象表达式来实现两个接口。其中一个接口是IDisposable。我希望能够使用这个对象表达式的结果来使用“use”关键字,但我有一个错误:
Type constraint mismatch. The type IConnMan is not compatible with type IDisposable The type 'IConnMan' is not compatible with the type 'IDisposable'
类型约束不匹配。类型IConnMan与类型i一次性的不兼容类型“IConnMan”与类型“IDisposable”不兼容
Why do I get this error?
为什么会出现这个错误?
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 个解决方案
#1
4
An object expression can have just a single type. The type is the type of the first (main) implemented interface - in your case, that's the IconnMan
type. F# doesn't allow you to use use
, because it doesn't statically know that the result of connman
function is IDisposable
.
对象表达式可以只有一个类型。类型是第一个(主)实现接口的类型——在您的例子中,这是IconnMan类型。f#不允许使用use,因为它不静态地知道connman函数的结果是IDisposable。
You could create interfaces in the object expression in the opposite order:
您可以按相反的顺序在对象表达式中创建接口:
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 = () }
Then you could write use cn = connman()
but you couldn't use functions of IConnMan
without casting (this is essentially the same as doing what Desco suggests). I don't think there is any nice solution to this problem.
然后,可以编写使用cn = connman()的函数,但是如果不进行强制转换,就不能使用IConnMan的函数(这基本上与Desco的建议相同)。我认为这个问题没有什么好的解决办法。
Could your IConnMan
interface inherit from IDisposable
?
您的IConnMan接口是否可以从IDisposable中继承?
#2
3
F# spec says:
f#规范说:
Object expressions are statically checked as follows. First, ty0 to tyn are checked and must all be named types. The overall type of the expression is ty0 and is asserted to be equal to the initial type of the expression. However, if ty0 is type equivalent to System.Object and where ty1 exists, then the overall type is instead ty1.
对象表达式的静态检查如下所示。首先,检查ty0到tyn,并且必须都是命名类型。表达式的总体类型是ty0,断言它等于表达式的初始类型。但是,如果ty0类型等同于系统。对象和ty1存在的位置,则整体类型为ty1。
so you can use type tests and downcasts or change the sequence of interfaces being implemented so IDisposable will be first
因此,您可以使用类型测试和下播或更改正在实现的接口序列,因此IDisposable是第一位的
let f() =
use cn = connman() :?> IDisposable
#1
4
An object expression can have just a single type. The type is the type of the first (main) implemented interface - in your case, that's the IconnMan
type. F# doesn't allow you to use use
, because it doesn't statically know that the result of connman
function is IDisposable
.
对象表达式可以只有一个类型。类型是第一个(主)实现接口的类型——在您的例子中,这是IconnMan类型。f#不允许使用use,因为它不静态地知道connman函数的结果是IDisposable。
You could create interfaces in the object expression in the opposite order:
您可以按相反的顺序在对象表达式中创建接口:
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 = () }
Then you could write use cn = connman()
but you couldn't use functions of IConnMan
without casting (this is essentially the same as doing what Desco suggests). I don't think there is any nice solution to this problem.
然后,可以编写使用cn = connman()的函数,但是如果不进行强制转换,就不能使用IConnMan的函数(这基本上与Desco的建议相同)。我认为这个问题没有什么好的解决办法。
Could your IConnMan
interface inherit from IDisposable
?
您的IConnMan接口是否可以从IDisposable中继承?
#2
3
F# spec says:
f#规范说:
Object expressions are statically checked as follows. First, ty0 to tyn are checked and must all be named types. The overall type of the expression is ty0 and is asserted to be equal to the initial type of the expression. However, if ty0 is type equivalent to System.Object and where ty1 exists, then the overall type is instead ty1.
对象表达式的静态检查如下所示。首先,检查ty0到tyn,并且必须都是命名类型。表达式的总体类型是ty0,断言它等于表达式的初始类型。但是,如果ty0类型等同于系统。对象和ty1存在的位置,则整体类型为ty1。
so you can use type tests and downcasts or change the sequence of interfaces being implemented so IDisposable will be first
因此,您可以使用类型测试和下播或更改正在实现的接口序列,因此IDisposable是第一位的
let f() =
use cn = connman() :?> IDisposable