简体   繁体   中英

F# implementation of interface method with type constraint

I have a stupid problem, I need to implement in F# class the interface which have following method:

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

And I am struggling myself doing it in F#. I have tried different ways. But the problem is that an object of type T must be returned. Null is not accepted:

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

Error: The member 'MyMethod<'T when 'T : not struct> : unit -> a' when a': not struct and 'a: null does not have the correct type to override the corresponding abstract method. The required signature is 'MyMethod<'T when 'T : not struct> : unit -> 'T when 'T: not struct'

So I have tried to put T as argument to the class, but still no I finished with error:

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

Error: The member 'MyMethod<'T when 'T : not struct> : unit -> 'T when 'T : not struct' does not have the correct type to override the corresponding abstract method.

Thank you for help.

Instead of returning null (which is inferred to have some type 'a , check by returning null :?> 'T ) you can use

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

I prefer __ over this when it's not used.

TL;DR;

The class constraint in C# implicitly includes null . Unfortunately specifying that in F# is not allowed:

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

results in:

The member 'MyMethod<'T when 'T : not struct and 'T : null> : unit -> 'T when 'T : not struct and 'T : null' does not have the correct type to override the corresponding abstract method. The required signature is 'MyMethod<'T when 'T : not struct> : unit -> 'T when 'T : not struct'.

But then, using classes and interfaces like these cross-language requires special attention anyways, because C# and the CLR allow null values whereas F# doesn't.

For comparison against null best overload F# isNull (see this answer ):

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

unless your type allows null when you can use standard isNull :

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM