A Generic Generics Problem

  • Thread starter Tom Jastrzebski
  • Start date
T

Tom Jastrzebski

Hello everybody,

Here is the problem I came across experimenting with Generics.
I would like to write a class or a struct adding integer to any other,
initially undefined *numeric type*.
So, my struct would look more or less like:

struct MySum<T> where T : struct {
public static T AddInteger(T value, int i) {
return value + i;
}
}

Of course the above code does not compile since the compiler does not even
know whether <T> implements "+" operator or not.
Even it it would it would not know if <T> can be converted to Int32 or not.
I tried different solutions, but none of them worked.

The described problem is just a simplified illustration of an issue I
experienced trying to implemented more complex functionality.

Disclaimer: yes, I know that this is not the way generics are intended to be
used in the first place, but may be the solution exists.

Thanks,
Tomasz
 
N

Nicholas Paldino [.NET/C# MVP]

Tom,

The only way to do this would be to check the type T to see if it is
convertable to something that supports the + operator (you could check for
the op_Addition static method, but that won't work for the primitive types).
Ultimately, this is very messy, and not really a good solution. It is the
only one that would work (you could check to see if T is of type int, uint,
double, etc, etc, and then cast value to a parameter of that type, and
perform the operation).

The reason it doesn't work is because the language doesn't support
constraints on supported operators, so the class compiler has no clue
whether or not the operator can be called. Perhaps in the future it will
happen, but Anders has mentioned on more than one time that they want to be
safe rather than sorry (meaning, take it slow with the constraint language
details).

Hope this helps.
 
T

Tom Jastrzebski

Nicholas,

Thank you for your response.

I can think of some solutions how to convert unknown type T to a known type,
and do my calculations.
Numeric types implement IConvertible, so it could be used as a constraint
and to facilitate conversion.

However, I have completely no clue how to convert my temp known type back to
the original, unknown type T.
It would be nice to have some sort of Converter<T> class with a lot of
overloaded From() methods, or if numeric types implemented IConvertible<T> -
a generic version of IConvertible.

Just a thought, but may be it is not such a bad idea.

Tomasz


Nicholas Paldino said:
Tom,

The only way to do this would be to check the type T to see if it is
convertable to something that supports the + operator (you could check for
the op_Addition static method, but that won't work for the primitive
types). Ultimately, this is very messy, and not really a good solution.
It is the only one that would work (you could check to see if T is of type
int, uint, double, etc, etc, and then cast value to a parameter of that
type, and perform the operation).

The reason it doesn't work is because the language doesn't support
constraints on supported operators, so the class compiler has no clue
whether or not the operator can be called. Perhaps in the future it will
happen, but Anders has mentioned on more than one time that they want to
be safe rather than sorry (meaning, take it slow with the constraint
language details).

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)


Tom Jastrzebski said:
Hello everybody,

Here is the problem I came across experimenting with Generics.
I would like to write a class or a struct adding integer to any other,
initially undefined *numeric type*.
So, my struct would look more or less like:

struct MySum<T> where T : struct {
public static T AddInteger(T value, int i) {
return value + i;
}
}

Of course the above code does not compile since the compiler does not
even know whether <T> implements "+" operator or not.
Even it it would it would not know if <T> can be converted to Int32 or
not.
I tried different solutions, but none of them worked.

The described problem is just a simplified illustration of an issue I
experienced trying to implemented more complex functionality.

Disclaimer: yes, I know that this is not the way generics are intended to
be used in the first place, but may be the solution exists.

Thanks,
Tomasz
 
N

Nicholas Paldino [.NET/C# MVP]

Tom,

If the type has a TypeConverter-derived class associated with it, you
can call the static GetConverter method on the TypeDescriptor class to get
the TypeConverter (which you can use to convert to other types).

If not, you will have to check for the IConvertable interface and use
that.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Tom Jastrzebski said:
Nicholas,

Thank you for your response.

I can think of some solutions how to convert unknown type T to a known
type, and do my calculations.
Numeric types implement IConvertible, so it could be used as a constraint
and to facilitate conversion.

However, I have completely no clue how to convert my temp known type back
to the original, unknown type T.
It would be nice to have some sort of Converter<T> class with a lot of
overloaded From() methods, or if numeric types implemented
IConvertible<T> - a generic version of IConvertible.

Just a thought, but may be it is not such a bad idea.

Tomasz


Nicholas Paldino said:
Tom,

The only way to do this would be to check the type T to see if it is
convertable to something that supports the + operator (you could check
for the op_Addition static method, but that won't work for the primitive
types). Ultimately, this is very messy, and not really a good solution.
It is the only one that would work (you could check to see if T is of
type int, uint, double, etc, etc, and then cast value to a parameter of
that type, and perform the operation).

The reason it doesn't work is because the language doesn't support
constraints on supported operators, so the class compiler has no clue
whether or not the operator can be called. Perhaps in the future it will
happen, but Anders has mentioned on more than one time that they want to
be safe rather than sorry (meaning, take it slow with the constraint
language details).

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)


Tom Jastrzebski said:
Hello everybody,

Here is the problem I came across experimenting with Generics.
I would like to write a class or a struct adding integer to any other,
initially undefined *numeric type*.
So, my struct would look more or less like:

struct MySum<T> where T : struct {
public static T AddInteger(T value, int i) {
return value + i;
}
}

Of course the above code does not compile since the compiler does not
even know whether <T> implements "+" operator or not.
Even it it would it would not know if <T> can be converted to Int32 or
not.
I tried different solutions, but none of them worked.

The described problem is just a simplified illustration of an issue I
experienced trying to implemented more complex functionality.

Disclaimer: yes, I know that this is not the way generics are intended
to be used in the first place, but may be the solution exists.

Thanks,
Tomasz
 
T

Tom Jastrzebski

Nicholas,

Thank you for the good idea. So, my example could look as follows:

struct MySum<T> where T : struct, IConvertible
{
public static T AddInteger(T value, int i)
{
TypeConverter tc = TypeDescriptor.GetConverter(typeof(T));
long l =
((IConvertible)value).ToInt64(NumberFormatInfo.InvariantInfo);
l = l + i;
return (T)tc.ConvertTo(l, typeof(T));
}
}

The only problem I see is generally unnecessary boxing in the last line.
I hope that Microsoft will eventually provide us with a generics version of
TypeConverter, or something similar.
I think that would the best solution.

Tomasz



Nicholas Paldino said:
Tom,

If the type has a TypeConverter-derived class associated with it, you
can call the static GetConverter method on the TypeDescriptor class to get
the TypeConverter (which you can use to convert to other types).

If not, you will have to check for the IConvertable interface and use
that.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Tom Jastrzebski said:
Nicholas,

Thank you for your response.

I can think of some solutions how to convert unknown type T to a known
type, and do my calculations.
Numeric types implement IConvertible, so it could be used as a constraint
and to facilitate conversion.

However, I have completely no clue how to convert my temp known type back
to the original, unknown type T.
It would be nice to have some sort of Converter<T> class with a lot of
overloaded From() methods, or if numeric types implemented
IConvertible<T> - a generic version of IConvertible.

Just a thought, but may be it is not such a bad idea.

Tomasz


Nicholas Paldino said:
Tom,

The only way to do this would be to check the type T to see if it is
convertable to something that supports the + operator (you could check
for the op_Addition static method, but that won't work for the primitive
types). Ultimately, this is very messy, and not really a good solution.
It is the only one that would work (you could check to see if T is of
type int, uint, double, etc, etc, and then cast value to a parameter of
that type, and perform the operation).

The reason it doesn't work is because the language doesn't support
constraints on supported operators, so the class compiler has no clue
whether or not the operator can be called. Perhaps in the future it
will happen, but Anders has mentioned on more than one time that they
want to be safe rather than sorry (meaning, take it slow with the
constraint language details).

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)


Hello everybody,

Here is the problem I came across experimenting with Generics.
I would like to write a class or a struct adding integer to any other,
initially undefined *numeric type*.
So, my struct would look more or less like:

struct MySum<T> where T : struct {
public static T AddInteger(T value, int i) {
return value + i;
}
}

Of course the above code does not compile since the compiler does not
even know whether <T> implements "+" operator or not.
Even it it would it would not know if <T> can be converted to Int32 or
not.
I tried different solutions, but none of them worked.

The described problem is just a simplified illustration of an issue I
experienced trying to implemented more complex functionality.

Disclaimer: yes, I know that this is not the way generics are intended
to be used in the first place, but may be the solution exists.

Thanks,
Tomasz
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top