Как вы можете статически связывать типы вместе (как в TypeToType & lt; T & gt;) в C # с использованием обобщений?

Скажем, у меня есть набор типов формы BooleanAttribute, ContinuousAttribute, FiveStarAttributeи т. д. Каждый из них концептуально связан с типом значения (например, bool, double, int для примеров выше.) Каждый также наследует от общего базового класса AttributeBase,

Скажем, у меня есть еще один общий класс под названием AttributeUpgrade<Attr> который содержит в качестве члена экземпляр Attr, где Attr наследуется от AttributeBase, Я также хотел бы, чтобы он содержал два экземпляра (старый и новый) типа значения, концептуально связанного с Attr,

С шаблонами C ++ это было бы тривиально. В каждом типе в наборе атрибутов я определяю typedef для ValueType и объявляю своих членов как

template <typename Attr>
class AttributeUpgrade
{
Attr attribute;

typename Attr::ValueType old;
typename Attr::ValueType new;
...

До сих пор эквивалентное решение в C #, или что-нибудь рядом с ним, намекало на меня. Любые решения приветствуются, даже если они предполагают разрыв части структуры в примере. В моем нынешнем виде я стремлюсь отказаться от безопасности типов и просто набирать старые и новые как объекты. Спасибо!

2

Решение

Попробуй это:

class AttributeUpgrade<T> where T : Attr
{
T oldOne;
T newOne;
}

И помните, что new является зарезервированным ключевым словом.

Предложение where является необязательным, но вы можете ограничить используемые типы Attr

Редактировать: Я упустил спецификаторы доступа для класса и членов для ясности, поскольку я не знаю, какой уровень доступа необходим.

Редактировать: Ответ из комментариев:

В моих словах: вы хотите повторно использовать параметр шаблона из Attr в объявлении AttributeUpgrade, не вводя новый универсальный параметр в AttributeUpdate.

Это не может быть сделано в C #.

Вам либо понадобится второй параметр шаблона, либо прибегните к использованию GetType() на внутренний тип Attr, чтобы получить System.Type (но, как вы знаете об этом, здесь нет безопасности типов).
C ++ решает эту проблему, используя typedef в классах. Наиболее близкими здесь являются псевдонимы, но они не могут предоставить нужную вам функцию.

См. Stackoverflow.com/questions/19790556/c-sharp-typedef-generics.

На самом деле, я думаю, что «лучшим» способом здесь было бы добавить еще один параметр шаблона, и во время выполнения (!) Утверждать, что внутренний тип Attr равен тому, что в AttributeUpgrade,

1

Другие решения

Похоже, вы пытаетесь писать шаблоны C ++ с использованием обобщений C #. Однако они немного отличаются как по концепции, так и по исполнению. Что вы на самом деле пытаетесь создать? Какую оригинальную проблему вы решаете?

Если я понимаю ваше намерение, простое решение состоит в том, чтобы сам AttributeBase был универсальным.

class AttributeBase<T>
{
T value;
}

class BooleanAttribute: AttributeBase<bool>
{

}

class AttributeUpgrade<T>
{
AttributeBase<T> attribute;

T oldValue;
T newValue;
}

// Or alternatively...
class AttributeUpgrade<T, K>
where T : AttributeBase<K>
{
T attribute;

K oldValue;
K newValue;
}

Если вы не можете позволить себе использовать базовый базовый класс, вы можете использовать интерфейсы для переопределения некоторых вещей по мере необходимости (т. Е. Либо иметь универсальный шаблон и неуниверсальный класс, либо наоборот), но я ожидаю, что это не так , поскольку у вас будет такая же проблема с шаблонами C ++.

В отличие от шаблонов, дженерики C # разрешаются по требованию во время выполнения, они не являются просто этапом предварительной обработки во время компиляции. Это, конечно, имеет свои плюсы и минусы, и они совсем не одно и то же. Это не означает, что вы не можете использовать универсальные шаблоны для решения проблемы, которую вы решили с помощью шаблонов в C ++, — это не просто синтаксический сахар, как в C ++. Вы можете использовать генераторы кода, чтобы сделать что-то, как делают шаблоны C ++, но это выходит за рамки SO вопроса: D

0

По вопросам рекламы [email protected]