我有一个愚蠢的问题,我需要在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'没有正确的类型来覆盖相应的抽象方法时。
感谢您的帮助。
答案 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