use*_*704 5 f# interface type-constraints
我有一个愚蠢的问题,我需要在F#类中实现具有以下方法的接口:
public interface IMyInterface
{
T MyMethod<T>() where T : class;
}
Run Code Online (Sandbox Code Playgroud)
我在F#中努力做到这一点.我尝试过不同的方法.但问题是必须返回类型为T的对象.Null不被接受:
type public Implementation() =
interface IMyInterface with
member this.MyMethod<'T when 'T : not struct>() = null
Run Code Online (Sandbox Code Playgroud)
错误:成员'MyMethod <'T当'T:not struct>:unit - > a'when a':not struct和'a:null没有正确的类型来覆盖相应的抽象方法.'T:not struct>时所需的签名是'MyMethod <'T:单位 - >'T时'T:not struct'
所以我试图将T作为参数添加到类中,但仍然没有完成错误:
type public Implementation(data : 'T when 'T : not struct) =
interface IMyInterface with
member this.MyMethod<'T when 'T : not struct>() = data
Run Code Online (Sandbox Code Playgroud)
错误:成员'MyMethod <'T当'T:not struct>:unit - >'T时'T:not struct'没有正确的类型来覆盖相应的抽象方法.
谢谢你的帮助.
您可以使用,而不是返回null(推断为具有某种类型'a,通过返回检查null :?> 'T)
type public Implementation() =
interface IMyInterface with
member __.MyMethod<'T when 'T : not struct>() = Unchecked.defaultof<'T>
Run Code Online (Sandbox Code Playgroud)
我喜欢__过this的时候不是用它.
TL; DR;
classC#中的约束隐含地包括null.不幸的是,不允许在F#中指定:
member __.MyMethod<'T when 'T : not struct and 'T : null>() = Unchecked.defaultof<'T>
Run Code Online (Sandbox Code Playgroud)
结果是:
'T:not struct和'T:null>时的成员'MyMethod <'T:单位 - >'T时'T:not struct和'T:null'没有正确的类型来覆盖相应的抽象方法.当'T:not struct>:unit - >'T时'T:not struct'时,所需的签名是'MyMethod <'T.
但是,使用像这些跨语言的类和接口需要特别注意,因为C#和CLR允许null值,而F#不允许.
为了比较null最佳超载F#isNull(见这个答案):
let inline isNull (x:^T when ^T : not struct) = obj.ReferenceEquals (x, null)
Run Code Online (Sandbox Code Playgroud)
除非您的类型允许null使用标准isNull:
[<AllowNullLiteral>]
type Foo() =
member __.Bar() = ()
(Implementation() :> IMyInterface).MyMethod<Foo>() |> isNull // true
Run Code Online (Sandbox Code Playgroud)