Say I have a suite of types of the form BooleanAttribute
, ContinuousAttribute
, FiveStarAttribute
, etc. Each of these is conceptually bound to a value type (e.g. bool
, double
, int
for the examples above.) Each also inherits from a common base class AttributeBase
.
Say I have another generic class called AttributeUpgrade<Attr>
that contains as a member an instance of Attr
, where Attr
inherits from AttributeBase
. I would also like it to contain two instances (old and new) of the value type conceptually bound to Attr
.
With C++ templates, this would be trivial. In each type in the Attribute suite I would define a typedef for ValueType, and declare my members as
template <typename Attr>
class AttributeUpgrade
{
Attr attribute;
typename Attr::ValueType old;
typename Attr::ValueType new;
...
So far the equivalent solution in C#, or anything near it, has alluded me. Any solutions would be appreciated, even if they involve tearing apart some of the structure in the example. As it stands, I am headed towards dropping type-safety and just typing old and new as objects. Thank you!
Try this:
class AttributeUpgrade<T> where T : Attr
{
T oldOne;
T newOne;
}
And be aware that new
is a reserved keyword.
The where clause is optional but you might want to restrict the used types to Attr
Edit: I have omitted access specifiers on class and on members for the sake of clarity as I am not aware of what access level is needed.
Edit: Answer from comments:
In my words: You wish to re-use the template parameter from Attr in the declaration of AttributeUpgrade without introducing a new generic parameter to AttributeUpdate.
This cannot be done in C#.
You will either need the second template parameter or resort to the use of GetType()
on the Attr's inner type to get a System.Type
(but as you are aware of this, there is no type safety here).
C++ solves this by using typedefs in classes. The closest thing here are aliases but they cannot provide the feature you need.
See stackoverflow.com/questions/19790556/c-sharp-typedef-generics .
Indeed I think that the "best" way here would be to add another template parameter and runtime(!) assert that Attr's inner type is equal the one's in AttributeUpgrade
.