我正在尝试将我的桌面 .NET dll 编译到 WinRT 平台(目标 Windows 8.1)。它在桌面上运行良好,但在 WinRT 项目中,我的代码中有编译器错误:
internal static T[] CreateRuntime<T>(MemberInfo member, bool inherit)
{
return member.GetCustomAttributes(typeof(T), inherit).Select(attr => (T)attr).ToArray();
}
我不能投
Attribute
attr
到泛型参数 T
...但为什么只在 WinRT 上?语言是否有任何差异或可能导致这种情况的原因?
最佳答案
这是 C# 中类型转换规则的结果。从 C# 5.0 规范:
6.2.7 Explicit conversions involving type parameters
The following explicit conversions exist for a given type parameter T:
• From the effective base class C of T to T and from any base class of C to T. At run-time, if T is a value type, the conversion is executed as an unboxing conversion. Otherwise, the conversion is executed as an explicit reference conversion or identity conversion.
[…there are three other bullet points, but none apply here…]
The above rules do not permit a direct explicit conversion from an unconstrained type parameter to a non-interface type, which might be surprising. The reason for this rule is to prevent confusion and make the semantics of such conversions clear.
无约束,
T
的唯一已知基类是 System.Object
.但在 Winrt 中,GetCustomAttributes()
方法is implemented as an extension method , 返回 IEnumerable<Attribute>
而不是 object[]
返回 in the .NET API .因此变量 attr
类型为 Attribute
, 而不是 object
.因此,当您使用 .NET API 时,您可以从基类
object
进行转换。至T
,但是当您使用 Winrt 时,您不能从非基类 Attribute
进行转换至T
.您可以更改
T
的已知基类通过向方法声明添加约束:internal static T[] CreateRuntime<T>(MemberInfo member, bool inherit)
where T : Attribute
{
return member.GetCustomAttributes(typeof(T), inherit).Select(attr => (T)attr).ToArray();
}
基类为
T
现在被声明为 Attribute
,您现在可以从 Attribute
转换至T
.请注意,这在 .NET 和 Winrt 之间的语言实现上没有区别。这是完全相同的 C# 规则。只是您实际上正在处理
GetCustomeAttributes()
的不同实现。 ,返回值不同,使变量的类型 attr
不同,因此在每种情况下都会产生不同的结果。查看相关问题:
Cannot convert type 'System.Windows.Forms.Control' to 'T'
C# Problem with Generics
Casting to generic type fails in c#
我很失望,这些其他相关的问题和答案都没有解决问题的核心,这就是 C# 提出这个要求的原因。我已经尝试在上面这样做。但是,它们都涵盖了类似的场景,展示了在非 Winrt 代码的上下文中如何发生同样的事情。它们还说明了两种基本解决方案:
object
在转换到 T
之前.这绕过了通用转换,删除了上下文,以便编译器允许转换。恕我直言,这不太可取;但是如果由于某种原因无法添加约束(例如,您正在处理一种不适用于所有可能的 T
的特殊情况……无论这种实现是多么不可取),这将起作用。 关于c# - 无法将类型 'System.Attribute' 转换为泛型参数 'T' - 为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35494072/