2010-03-19 10 views
33

Mam kawałek kodu, w którym muszę dowiedzieć się, czy dany typ implementuje IEnumerable<T> (Nie dbam o T)F # odpowiednik C# typeof (IEnumerable <>)

Próbowałam (t:System.Type w przypadku wątpliwości)

let interfaces = t.GetInterfaces() 
let enumerbale = 
    interfaces.Any(fun t -> 
     t.GetGenericTypeDefinition() = typeof<IEnumerable<>> 
    ) 

jednak, że nie będzie kompilować (kompilacja nie lubi <>). Następnie wypróbowałem:

ale otrzymuję ostrzeżenie, że "a jest ograniczeniem dla obj. Nie chcę się dowiedzieć, czy zaimplementowano IEnumerable<obj>, ale IEnumerabl<>.

Każdy wie, na czym polega rozwiązanie i przy okazji może również skomentować powyższy kod.

+0

http://stackoverflow.com/questions/1652050/generic-type-definition- Składnia-na-f –

Odpowiedz

49

To powinno działać:

typedefof<System.IEnumerable<_>> 

EDIT

Jak zauważa Tomas, nie ma nic szczególnego w _ zamiennika tutaj; F # informuje, że typ obj jest najbardziej ogólnym typem stosowanym w tym kontekście, więc jest taki sam jak przy użyciu typedefof<System.IEnumerable<obj>>. W niektórych przypadkach sposób, w jaki to działa, może być jednak przeszkodą. Na przykład, jeśli zdefiniujesz interfejs type I<'a when 'a :> I<'a>> = interface end, nie możesz użyć typedefof<I<_>>, ponieważ I<obj> nie spełnia ogólnego ograniczenia, a F # nie może określić innego, bardziej odpowiedniego typu. Może się to zdarzyć nawet bez ograniczeń rekursywnych (np. type I<'a when 'a : struct and 'a :> System.ICloneable> = interface end. Jest to przeciwieństwo podejścia C#, które działa doskonale w analogicznych przypadkach:

Co do samego kodu, myślę, że będziesz chciał wprowadzić inne zmiany, . również takie jak zapewnienie, że interfejs jest rodzajowa przed wywołaniem GetGenericTypeDefinition Oto jak bym napisać funkcję testową.

(fun t -> t.IsGenericType && (t.GetGenericTypeDefinition() = typedefof<_ seq>)) 
+0

Twoje rozwiązanie uratowało mnie przed innym problemem :) z niezbyt użytecznym błędem "nieobsługiwanym ze względu na obecny stan obiektu", co jest sposobem na powiedzenie nie może wywołać getgenerictypedycja ón nietypowy typ –

17

o ile mi wiadomo, F # nie ma żadnego odpowiednika dla C# 's typeof(IEnumerable<>) jest ponieważ jest to specjalna składnia obsługiwana jawnie przez C#. W F #, typeof jest normalną funkcją, a argument typu musi być w pełni określonym typem. eneric definicja typu programowo tak:

let t = typeof<IEnumerable<obj>> 
let genericT = t.GetGenericTypeDefinition() 

Problem z roztworu IEnumerable<'a> jest to, że F # kompilator musi jeszcze znaleźć jakiś konkretny typ użyć (jako typ rodzajowy definicja nie jest prawidłowy typ). Jeśli wnioskowanie typu wnioskuje, że parametr typu nie jest w żaden sposób ograniczony, używa domyślnego typu, który jest obj.

EDYTOWANIE Nie wiedziałem o typedefof<IEnumerable<_>>, to bardzo przydatne! W każdym razie zwróć uwagę, że podkreślenie nie ma tu specjalnego znaczenia - rzeczywisty argument typu to nadal IEnumerable<obj>, ale funkcja wywołuje za sceną GetGenericTypeDefinition.

+0

Dzięki za wyjaśnienie _ –

Powiązane problemy