2010-05-04 2 views
2

я определяю следующее расширение типа:Где «неопределенный тип»?

type System.Reflection.MemberInfo with 
    member x.GetAttribute<'T when 'T :> Attribute>(required, inherit') = 
     match required, Attribute.GetCustomAttribute(x, typeof<'T>, inherit') with 
     | true, null -> invalidOp (sprintf "Missing required attribute: %s" typeof<'T>.FullName) 
     | _, attr -> attr :> 'T 

Выражение последнего матча (attr :> 'T) выдает ошибку:

Статического принуждение от атрибута к «T включает неопределенный тип на основе информации, предварительной к этой программной точке. Статические принуждения не допускаются к некоторым типам. Нужны дополнительные аннотации.

Я пробовал аннотировать возвращаемый тип функции, но получил тот же результат. Мне не хотелось бы менять это на динамический бросок. Есть ли способ сделать статическую работу?

ответ

3

Должно быть динамическое приведение, не так ли? У вас есть объект, статический тип которого - System.Attribute, и вы хотите сбрасывать его на конкретный конкретный тип.

open System 
type System.Reflection.MemberInfo with 
    member x.GetAttribute<'T when 'T :> Attribute>(required, inherit') = // ' 
    match required, Attribute.GetCustomAttribute(x, typeof<'T>, inherit') with 
    | true, null -> invalidOp (
     sprintf "Missing required attribute: %s" typeof<'T>.FullName) // ' 
    | _, attr -> attr :?> 'T 
+0

Я полагаю, что так. Я думаю, что меня сбросил аналогичный код на C#, где динамические и статические роли имеют одинаковый синтаксис. Это тоже должно быть динамическое кастинг на C#. – Daniel

0

Исправленный код, в случае, если он приносит пользу никому (код Брайана прав тоже ... Я просто предпочитаю аннотацию типа в подписи):

type System.Reflection.MemberInfo with 
    member x.GetAttribute<'T when 'T :> Attribute>(required, inherit') : 'T = 
     match required, Attribute.GetCustomAttribute(x, typeof<'T>, inherit') with 
     | true, null -> invalidOp (sprintf "Missing required attribute: %s" typeof<'T>.FullName) 
     | _, attr -> downcast attr 
1

Чтобы уточнить смысл ошибки message - компилятор делает разницу между статическим литьем :> (который всегда безопасен, например, литье от Random до Object) и динамическим литьем :?> (что может быть неудачным).

В вашем случае вам необходимо использовать динамический приведение. Это то, что означает, что компилятор:

  • Он говорит, что «Статическое принуждение от атрибута к 'T включает неопределенный тип». Это означает, что он не знает (во время компиляции) то, что является фактическим типом, используемым вместо общего параметра 'T.

  • В результате компилятор не может проверить, будет ли всегда выполнено преобразование с Attribute в 'T (что требуется в случае статических принуждений). Если, например, компилятор определил, что тип 'T будет всегда Object, тогда использование статического принуждения будет действительным.

Смежные вопросы