具有类型约束的接口方法的F#实现

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'没有正确的类型来覆盖相应的抽象方法.

谢谢你的帮助.

Car*_*Dev 6

您可以使用,而不是返回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)

  • 这个答案是正确的,但根据你需要这个类的上下文,它可能不是你想要的.如果``'T``是一个类,这个实现将返回``null``,如果它是一个F#类,编译器将不会(轻松)让它与``null``进行比较.所以请注意这一点. (3认同)