Это является следствием правил преобразования типов в C#. Из спецификации C# 5.0: Параметры
6.2.7 Явные преобразования с участием типа
Существуют следующие явные преобразования для данного параметра типа T:
• От эффективного базового класса С Т до Т и из любого базового класса C в T. Во время выполнения, если T является типом значения, преобразование выполняется как преобразование unboxing. В противном случае преобразование выполняется как явное преобразование ссылок или преобразование идентичности.
[& hellip; есть три точки пули, но ни один не применять здесь и hellip;]
Приведенные выше правила не допускают прямого явного преобразования из неограниченного параметра типа к типу не-интерфейс, который может быть удивительно , Причина этого правила заключается в том, чтобы предотвратить путаницу и сделать семантику таких преобразований понятными.
Безграничных, единственные известный базовый класс 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. Они также иллюстрируют два основных решения:
- Используйте ограничение на общий параметр (как я предлагаю здесь)
- Cast для
object
перед заливкой в T
. Это обходит общее преобразование, удаляя контекст, чтобы компилятор разрешал выполнение. ИМХО это гораздо менее предпочтительно; но если вы не можете добавить ограничение по какой-либо причине (например, вы имеете дело со специальным случаем, который не применяется ко всем возможным T
& hellip, однако нежелательны такие реализации), это будет работать.
Вы помещали ограничение 'where T: Attribute'? Определение 'T' было бы полезно увидеть – Rob
Это также может быть полезно: http://www.minddriven.de/index.php/technology/dot-net/net-winrt-get-custom-attributes-from- enum-value – Rob
@Rob спасибо, но мой вопрос касается различий в компиляторах - не проверка кода;) btw, когда я помещаю 'T: Attribute', ошибка исчезает. – Vlad