2016-07-13 9 views
5

mam głupi problem, muszę wdrożyć w F # klasy interfejsu, które następujące metody:F # wdrożenie metody interfejsu z typu ograniczenia

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

A ja zmagam się robi w F #. Próbowałem na różne sposoby. Problem polega jednak na tym, że obiekt typu T musi zostać zwrócony. Null nie są akceptowane:

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

Błąd: Człon 'myMethod < 'T kiedy 'T: nie struct>: Unit -> a' kiedy': nie struct oraz': null nie mają poprawny typ, aby zastąpić odpowiednią metodę abstrakcyjną. Wymagany podpis to "MyMethod <" T, gdy "T: not struct>: unit ->" T, gdy "T: not struct"

Więc próbowałem postawić T jako argument dla klasy, ale nadal nie skończyłem z błędem:

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

błąd: człon 'myMethod <' t kiedy 'T: nie struct>: jednostka ->' T kiedy 'T: nie struct' nie ma odpowiedniego typu przesłonić odpowiednia abstrakcyjna metoda.

Dziękuję za pomoc.

Odpowiedz

6

Zamiast powrocie null (który jest wywnioskować mieć jakiś rodzaj 'a sprawdzić wracając null :?> 'T) można użyć

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

Wolę __ nad this gdy nie jest używany.

TL; DR;

Ograniczenie class w języku C# domyślnie obejmuje null. Niestety, określając, że w F # nie jest dozwolone: ​​

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

wyniki w:

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

Ale potem, za pomocą klas i interfejsy takie jak krzyżowego języka wymaga szczególnej uwagi tak czy inaczej, bo C# i CLR pozwalają null wartości, podczas gdy F # nie.

Dla porównania przed null najlepszej przeciążenie F # isNull (zobacz answer):

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

chyba twój typ pozwala null kiedy można wykorzystać standardowy isNull:

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

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

Ta odpowiedź jest poprawna, ale w zależności od w kontekście, w którym potrzebujesz tej klasy, może nie być to, czego chcesz. Jeśli '' 'T'' jest klasą, ta implementacja zwróci '' null'', a jeśli jest to klasa F #, kompilator nie będzie (łatwo) mógł go porównać do '' null''. Więc szukajcie tego. –

+0

@OverlordZurg Dzięki za wskazanie tego. Dodałem TL; DR; :-) – CaringDev

+1

Kod w [tej odpowiedzi] (http: // stackoverflow.com/a/10746877/636019) wykonuje testy zerowe dla dowolnego typu referencyjnego, F # lub innego. – ildjarn

Powiązane problemy