我正在定义以下类型扩展名:
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的静态强制涉及基于此程序点之前的信息的不确定类型。某些类型不允许静态强制。需要进一步的类型注释。
我试过注释函数返回类型,但得到了相同的结果。我不想把它改成动态演员。有没有办法使静态演员工作?
答案 0 :(得分: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
答案 1 :(得分:1)
为了澄清错误消息的含义 - 编译器在静态转换:>
(总是安全的,例如从Random
转换为Object
)和动态转换{之间的区别。 {1}}(可能会失败)。
在您的情况下,您需要使用动态强制转换。这就是编译器的含义:
它说“从属性到:?>
的静态强制涉及不确定类型”。这意味着它(在编译时)不知道用于代替泛型参数'T
的实际类型是什么。
因此,编译器无法检查从'T
到Attribute
的转换是否总是成功(这在静态强制的情况下是必需的)。例如,如果编译器确定'T
的类型将始终为'T
,那么使用静态强制将是有效的。
答案 2 :(得分:0)
更正后的代码,以防任何人受益(Brian的代码也是正确的......我只是更喜欢签名中的类型注释):
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