Почему C # не поддерживает дженерики дженериков (дженерики с параметризованными типами)? - PullRequest
5 голосов
/ 07 октября 2011

В последнее время (возможно, из-за недостатков дизайна) я столкнулся с обычной задачей, когда требовалось иметь коллекцию MyType<T>, где T не является фиксированной (т. Е. Несколько различных экземпляров универсальных шаблонов в одной коллекции).

Какшироко предлагается (для таких случаев) абстрактный класс:

public abstract class MyType {}
public class MyType<T>: MyType {}

, а затем у меня есть коллекция MyType.Однако для этой коллекции у меня было ограничение на наличие не более одного элемента для любого типа T.

Следовательно, я сделал немного пользовательской реализации ICollection<TBase>.Я хотел включить туда метод Get<TParam>() для получения элемента, соответствующего типу TParam.Позже будет использоваться как:

MyCollection<MyType> collection = new MyCollection<MyType>();
MyType<int> myInt = collection.Get<int>();

Однако я неожиданно обнаружил, что не могу даже объявить это:

public TCustom<TParam> Get<TParam, TCustom<TParam>>() { } //this won't compile

, потому что внутренние дженерики (или так называемые «дженерики дженериков») не поддерживаются ни C #, ни .NET (я полагаю).Как вы думаете, были ли какие-то конкретные причины таких ограничений (кроме сложности)?

ОБНОВЛЕНИЕ 1. Запрос версии компилятора и ошибок компилятора.

Microsoft C #.NET 3.5 (Visual Studio 2010).Ошибки:

ошибка CS0081: объявление параметра типа должно быть идентификатором, а не типом

ошибка CS0246: не удалось найти имя типа или пространства имен 'TCustom' (вы пропускаетеиспользуя директиву или ссылку на сборку?)

ОБНОВЛЕНИЕ 2. На вопрос, нужно ли мне исправить или объяснить, почему.Я действительно хочу знать ПОЧЕМУ .Но если у вас есть хорошие решения этой проблемы, вы также можете.

ОБНОВЛЕНИЕ 3. На этот вопрос можно ответить уже в этом сообщении в блоге .Похоже, что команда CLR была под большим давлением, чтобы не усложнять язык.

Ответы [ 2 ]

1 голос
/ 07 октября 2011

В этом случае вы можете просто скрыть данные в неуниверсальном словаре:

private Dictionary<Type, object> _Data;

, а затем ваш Get метод:

public MyType<TParam> Get<TParam>()
{ 
    return (MyType<TParam>)_Data[typeof(TParam)];
}

Если типы TParam не связаны, нет общей структуры данных, которая в любом случае обеспечит вам безопасность типов, так зачем даже пытаться?

0 голосов
/ 07 октября 2011

Почему именно вам нужно

public TCustom<TParam> Get<TParam, TCustom<TParam>>() { } 

Когда универсальный тип (MyType в вашем случае) известен, вы не можете просто сделать

public MyType<TParam> Get<TParam>() { 
  return (MyType<TParam>)_items.FirstOrDefault(i => i is MyType<TParam>);
}

Или я что-то упустил

...