【问题标题】:Cannot convert type 'System.Attribute' to generic argument 'T' - why?无法将类型“System.Attribute”转换为通用参数“T” - 为什么?
【发布时间】:2016-02-19 11:46:00
【问题描述】:

我正在尝试将我的桌面 .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 上?语言上是否有任何差异或可能导致这种情况的原因?

【问题讨论】:

  • 您是否设置了约束 where T : AttributeT 的定义会很有用
  • @Rob 谢谢,但我的问题是关于编译器差异 - 不是代码审查;)顺便说一句,当我输入 T : Attribute 时,错误消失了。

标签: c# compiler-errors windows-runtime windows-8.1 system.reflection


【解决方案1】:

这是 C# 中类型转换规则的结果。来自 C# 5.0 规范:

6.2.7 涉及类型参数的显式转换
给定类型参数 T 存在以下显式转换:
• 从 T 的有效基类 C 到 T 以及从 C 的任何基类到 T。在运行时,如果 T 是值类型,则转换作为拆箱转换执行。否则,转换将作为显式引用转换或标识转换执行。

[…还有其他三个要点,但此处不适用…]

上述规则不允许从不受约束的类型参数直接显式转换为非接口类型,这可能令人惊讶。制定此规则的原因是为了防止混淆并使此类转换的语义清晰。

不受约束,T 的唯一已知基类是 System.Object。但是在 Winrt 中,GetCustomAttributes() 方法 is implemented as an extension method,返回 IEnumerable&lt;Attribute&gt; 而不是返回 in the .NET APIobject[]。因此变量attr 的类型为Attribute,而不是object

所以当你使用.NET API时,你可以从基类object转换成T,但是当你使用Winrt时,你不能从非基类Attribute转换成@ 987654337@.

您可以通过在方法声明中添加约束来更改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 代码的上下文中如何发生同样的事情。它们还说明了两种基本解决方案:

  1. 对泛型参数使用约束(我在此建议)
  2. 在转换为 T 之前转换为 object。这绕过了通用转换,删除了上下文,以便编译器允许转换。恕我直言,这不太可取;但如果由于某种原因无法添加约束(例如,您正在处理一种不适用于所有可能的T 的特殊情况......无论这种实现是多么不受欢迎),这将起作用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-25
    • 2015-03-23
    • 1970-01-01
    • 2019-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多