Массив универсального класса с неопределенным типом - PullRequest
9 голосов
/ 07 марта 2011

Возможно ли в C # создать массив неопределенных универсальных типов?Что-то вроде этого:

ShaderParam<>[] params = new ShaderParam<>[5];
params[0] = new ShaderParam<float>();

Или это просто невозможно из-за строгой типизации в C #?

Ответы [ 8 ]

16 голосов
/ 07 марта 2011

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

ShaderParam[] params = new ShaderParam[5]; // Note no generics
params[0] = new ShaderParam<float>(); // If ShaderParam<T> extends ShaderParam

Я предполагаю, что это тип XNA, который вы не можете контролировать.

7 голосов
/ 07 марта 2011

Вы могли бы использовать ковариантный интерфейс для ShaderParam<T>:

interface IShaderParam<out T> { ... }
class ShaderParam<T> : IShaderParam<T> { ... }

Использование:

IShaderParam<object>[] parameters = new IShaderParam<object>[5];
parameters[0] = new ShaderParam<string>(); // <- note the string!

Но вы не можете использовать его с типами значений, такими как float в вашем примере. Ковариация действительна только для ссылочных типов (например, string в примере my ). Вы также не можете использовать , если параметр типа появляется в противоположных позициях, например, в качестве параметров метода. Тем не менее, было бы полезно узнать об этой технике.

2 голосов
/ 07 марта 2011

Это не имеет смысла.

Что произойдет, если вы напишите params[3]?
Какого типа это будет?

Возможно, вы захотите создать неуниверсальныйбазовый класс или интерфейс и использовать их массив.

1 голос
/ 04 мая 2016

Довольно поздно к игре, но вот как: http://www.codeproject.com/Articles/1097830/Down-the-Rabbit-Hole-with-Array-of-Generics

1 голос
/ 07 марта 2011

создать массив неопределенных универсальных типов:

Object[] ArrayOfObjects = new Object[5];
ArrayOfObjects[0] = 1.1;
ArrayOfObjects[1] = "Hello,I am an Object";
ArrayOfObjects[2] = new DateTime(1000000);

System.Console.WriteLine(ArrayOfObjects[0]);
System.Console.WriteLine(ArrayOfObjects[1]);
System.Console.WriteLine(ArrayOfObjects[2]);

Если вам нужно выполнить некоторые специфические для типа действия над объектом, вы можете использовать Reflection

Надеюсь, это поможет.

1 голос
/ 07 марта 2011

Нет, понятие ShaderParam<> не имеет смысла в том, что касается экземпляра. Другими словами, бетон ShaderParam<float> является , а не экземпляром ShaderParam<>. Следовательно, объявленный тип массива будет недопустимым для хранения этого экземпляра. (Помимо того факта, что это уже недопустимый синтаксис для начала.)

1 голос
/ 07 марта 2011

Это возможно в универсальном классе или универсальном методе расширения , где T определено:

ShaderParam<T>[] params = new ShaderParam<T>[5];
0 голосов
/ 07 марта 2011

Не напрямую.Закрытый универсальный тип - это особый «тип» за кулисами, поэтому даже открытый универсальный формат является слишком общим, чтобы быть «сильным типом».

Лучшее решение, которое я могу придумать, которое я использовал ранее, - это создать неуниверсального предка для универсального класса.Будет ли это решение работать, зависит от того, для чего вы планируете использовать массив.

...