2016-07-13 15 views
5

ich ein dummes Problem haben, muss ich die Schnittstelle in F # Klasse implementieren, wobei das Verfahren folgende haben:F # Implementierung von Interface-Methode mit Typeinschränkung

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

Und ich habe Schwierigkeiten, mich es in F # zu tun. Ich habe verschiedene Wege ausprobiert. Das Problem ist jedoch, dass ein Objekt vom Typ T zurückgegeben werden muss. Null ist nicht zulässig:

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

Fehler: Das Mitglied '< MyMethod 'T, wenn T: nicht> struct: unit -> a ', wenn ein': nicht struct und' a: null nicht über die korrekter Typ, um die entsprechende abstrakte Methode zu überschreiben. Die erforderliche Unterschrift ist 'MyMethod <' T, wenn T: nicht> struct: unit -> 'T, wenn T: nicht struct'

So habe ich versucht, T als Argument für die Klasse zu setzen, aber noch keine ich beenden mit Fehler:

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

Fehler: Das Mitglied 'MyMethod <' T, wenn T: nicht struct>: unit -> 'T, wenn T: nicht struct' hat nicht die richtige Art außer Kraft zu setzen die entsprechende abstrakte Methode.

Vielen Dank für Ihre Hilfe.

Antwort

6

Statt null zurückzukehren (die geschlossen wird, eine Art 'a zu haben, überprüfen Sie durch die Rückkehr null :?> 'T) Sie

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

verwenden kann ich es vorziehen, __ über this, wenn es nicht verwendet wird.

TL; DR;

Die class Einschränkung in C# enthält implizit null.

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

Ergebnisse in: Leider, dass # darf nicht in F Angabe

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'.

Aber dann erfordert wie diese sprachübergreifende Klassen und Schnittstellen sowieso besondere Aufmerksamkeit, weil C# und der CLR erlauben null Werte, während F # nicht.

Zum Vergleich gegen null beste Überlastung F # isNull (siehe diese answer):

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

es sei denn, Ihre Art null erlaubt, wenn Sie Standard verwenden können isNull:

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

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

Diese Antwort ist richtig, aber je In dem Kontext, in dem Sie diese Klasse benötigen, ist es möglicherweise nicht das, was Sie möchten. Wenn '' 'T'' eine Klasse ist, gibt diese Implementierung '' null'' zurück, und wenn es eine F # -Klasse ist, wird der Compiler es nicht (einfach) mit '' null'' vergleichen lassen. Also halte Ausschau nach dem. –

+0

@OverlordZurg Vielen Dank, dass Sie darauf hingewiesen haben. Ich habe eine TL hinzugefügt, DR; :-) – CaringDev

+1

Der Code in [dieser Antwort] (http: // stackoverflow.com/a/10746877/636019) führt Nullprüfungen für jeden Referenztyp, F # oder anders durch. – ildjarn