具有类型约束

时间:2016-07-13 17:03:10

标签: interface f# type-constraints

我有一个愚蠢的问题,我需要在F#类中实现具有以下方法的接口:

public interface IMyInterface
{
    T MyMethod<T>() where T : class;
}

我在F#中努力做到这一点。我尝试过不同的方法。但问题是必须返回类型为T的对象。 Null不被接受:

type public Implementation() = 
    interface IMyInterface with
        member this.MyMethod<'T when 'T : not struct>() = null

错误:成员'MyMethod&lt;'T当'T:not struct&gt; :unit - &gt; a'when a':not struct和'a:null没有正确的类型来覆盖相应的抽象方法。 'T:not struct&gt;时所需的签名是'MyMethod&lt;'T :unit - &gt; '当'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

错误:成员'MyMethod&lt;'T当'T:not struct&gt; :unit - &gt; '当'T:not struct'没有正确的类型来覆盖相应的抽象方法时。

感谢您的帮助。

1 个答案:

答案 0 :(得分:6)

不是返回null(推断为某种类型为'a,而是通过返回null :?> 'T进行检查),您可以使用

type public Implementation() = 
    interface IMyInterface with
        member __.MyMethod<'T when 'T : not struct>() = Unchecked.defaultof<'T>

我更喜欢__而不是this

<强> TL; DR;

C#中的class约束隐式包含null。不幸的是,不允许在F#中指定:

member __.MyMethod<'T when 'T : not struct and 'T : null>() = Unchecked.defaultof<'T>

结果:

  

成员'MyMethod&lt;'T当'T:not struct and'T:null&gt; :unit - &gt; 'T when'T:not struct和'T:null'没有正确的类型来覆盖相应的抽象方法。 'T:not struct&gt;时所需的签名是'MyMethod&lt;'T :unit - &gt; 'T当'T:not struct'。

但是,使用像这些跨语言的类和接口需要特别注意,因为C#和CLR允许null值而F#不允许。

null最佳重载F#isNull进行比较(请参阅此answer):

let inline isNull (x:^T when ^T : not struct) = obj.ReferenceEquals (x, null)

除非您的类型允许null,否则您可以使用标准isNull

[<AllowNullLiteral>]
type Foo() =
    member __.Bar() = ()

(Implementation() :> IMyInterface).MyMethod<Foo>() |> isNull // true