Как проверить F #, реализует ли объект интерфейс

Прототипный код в С#:

if(obj1 is ISomeInterface) {
   do_something
}

Код в F #, который не компилируется:

match obj1 with 
| :? ISomeInterface -> do_something
| _ -> ()

Ответ 1

match box obj1 with 
| :? ISomeInterface -> do_something
| _ -> ()

Ответ 2

Чтобы добавить объяснения ответов desco и Brian, добавление box необходимо, если статический тип значения obj1 может не быть ссылочным типом .NET.

Если тип obj1 равен obj (введите псевдоним для System.Object), вы можете использовать сопоставление шаблонов без какого-либо бокса, потому что компилятор уже знает, что у вас есть ссылочный тип:

let obj1 : obj = upcast (...)
match obj1 with 
| :? ISomeInterface -> (do something)

В случае, если вам нужно box, когда тип obj1 является типичным параметром типа. В этом случае ваша функция может быть вызвана как с типами значений, так и с типами ссылок. Добавление box гарантирует, что вы выполняете тест типа для ссылочного типа (а не по типу значения, что невозможно).

Ответ 3

match box obj1 with ...

Я думаю (набрав с моего телефона:)

Ответ 4

Пока match box obj1 with ... выполняет задание, существует команда box IL, испускаемая компилятором F #. Инструкция Box опасна, поскольку в некоторых случаях она медленная.

Если вы знаете, что obj1 уже является ссылочным типом, рекомендуется использовать более быстрый подход :> obj:

match obj1 :> obj with
    | :? ISomeInterface -> (do something)

obj1 :> obj эквивалентно операции литья типа С# (object)obj1. Кроме того, компилятор F # оптимизирует эту чрезмерную операцию отбрасывания, когда проект построен в конфигурации Release, поэтому вы получаете самый быстрый код в этом случае.