Подтвердить что ты не робот

F # эквивалент С# typeof (IEnumerable <>)

У меня есть фрагмент кода, где мне нужно выяснить, реализует ли данный тип IEnumerable<T> (я не забочусь о T)

Я пробовал (t:System.Type в случае, если вы задаетесь вопросом)

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

однако это не будет компилироваться (компиляция не нравится < > ). Затем я попробовал

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

но получите предупреждение, что 'a является ограничением на obj. Я не хочу выяснять, реализована ли IEnumerable<obj>, но IEnumerabl<>.

Любой знает решение, и btw не стесняйтесь комментировать код выше.

4b9b3361

Ответ 1

Это должно работать:

typedefof<System.IEnumerable<_>>

ИЗМЕНИТЬ

Как отмечает Томаш, здесь нет ничего особенного в шаблоне _; F # указывает, что тип obj является наиболее общим применимым типом в этом контексте, так что это то же самое, что и при использовании typedefof<System.IEnumerable<obj>>. В некоторых случаях способ, которым это работает, может быть немного помехой. Например, если вы определяете интерфейс type I<'a when 'a :> I<'a>> = interface end, то вы не можете использовать typedefof<I<_>>, потому что I<obj> не удовлетворяет общему ограничению, а F # не может вывести еще один подходящий тип. Это может произойти даже без рекурсивных ограничений (например, type I<'a when 'a : struct and 'a :> System.ICloneable> = interface end. Это контрастирует с подходом С#, который отлично работает в аналогичных случаях.

Что касается самого кода, я думаю, вам также захочется внести некоторые другие изменения, например, чтобы общий интерфейс был до вызова GetGenericTypeDefinition. Вот как я бы написал тестовую функцию:

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

Ответ 2

Насколько я знаю, F # не имеет эквивалента С# typeof(IEnumerable<>). Это потому, что это специальный синтаксис, явно поддерживаемый С#. В F #, typeof - нормальная функция, и аргумент типа должен быть полностью определенным типом. Вы можете получить типичное определение типа следующим образом:

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

Проблема с вашим решением с IEnumerable<'a> заключается в том, что компилятору F # все еще нужно найти конкретный тип для использования (поскольку определение общего типа не является допустимым типом). Если вывод типа выводит, что параметр типа не ограничен каким-либо образом, он использует тип по умолчанию, который равен obj.

EDIT Я не знал о typedefof<IEnumerable<_>>, это очень полезно! В любом случае, обратите внимание, что подчеркивание здесь не имеет особого значения - фактический аргумент типа по-прежнему IEnumerable<obj>, но функция typedefof вызывает GetGenericTypeDefinition за сценой.