Динамическое приведение к интерфейсу - PullRequest
2 голосов
/ 12 июля 2011

Согласно сообщению http://cs.hubfs.net/forums/thread/3616.aspx, Мне нужно использовать функцию, подобную приведенной ниже, чтобы привести объект к интерфейсу, я запустил тест, это по-прежнему верно, ошибка:?> По-прежнему нетисправлено.

let cast<'a> o = (box o) :?> 'a
let ci = {  new Customer(18, Name = "fred") with
                override x.ToString() = x.Name 
            interface ITalk with
                member x.Talk() =
                    printfn "talk1111111" }

let italk = cast<ITalk> ci

if not (italk = null) then
    italk.Talk()

Есть ли более элегантный способ написания кода выше.Я подумываю создать другой оператор для замены:?>, Но я не могу получить параметр универсального типа, передаваемый как:?>

Ответы [ 2 ]

6 голосов
/ 12 июля 2011

Ваша функция cast не работает как оператор C # as - если объект не может быть приведен к указанному типу, он выдаст исключение, а не вернет ноль. Следовательно, проверка на то, что italk = null ничего не дает. Если вы хотите, чтобы функция cast возвращала ноль при сбое приведения, вместо того, чтобы выдавать исключение, вы можете написать это так:

let cast<'a when 'a : null> o =
    match box o with
    | :? 'a as output -> output
    | _ -> null

Тем не менее, это будет работать только с обнуляемыми типами, которые не включают структуры или (по умолчанию) типы F #. Я мог бы оставить вашу cast функцию такой, какая она есть, и сделать tryCast, которая использует опции.

let tryCast<'a> o =
    match box o with
    | :? 'a as output -> Some output
    | _ -> None

Тогда вы можете использовать это так:

ci |> tryCast<ITalk> |> Option.iter (fun it -> it.Talk())

В этом случае Option.iter занимает место вашего нулевого теста.

2 голосов
/ 12 июля 2011

Сопоставление с образцом обеспечивает более идиоматический способ написать это:

match box ci with
| :? ITalk as italk -> italk.Talk()
| _ -> ()

Или даже:

let bci = box ci
if bci :? ITalk then (bci :?> ITalk).Talk()

Я сохраняю функцию, подобную следующей, для того, когда я знаюТип теста пройдёт:

let coerce value = (box >> unbox) value

(coerce ci : ITalk).Talk()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...