473,327 Members | 2,025 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,327 software developers and data experts.

.NET generics & the .NET framework: not generic enough?

What follows is a discussion of my experience with .NET generics & the
..NET framework (as implemented in the Visual Studio 2005 Beta 1),
which leads to questions as to why certain things are the way they
are.

***** Summary & Questions *****

In a nutshell, the current .NET generics & .NET framework make it
sometimes difficult or even impossible to write truly generic code.
For example, it seems to be impossible to write a truly generic
Complex class or a truly generic Matrix class (see below for details).
Since this seems to be due to a combination of shortcomings in both
the .NET framework and the generics mechanism, I have two questions:

1. Why does the overload resolution mechanism only consider overloads
with generic parameters when we call a function with a generic
argument? If it considered other overloads as well, this would allow
us to work around classes that do not implement the proper generic
interfaces (see below for an example).

2. Why do .NET framework classes for primitive types (Byte, Int32,
Decimal, Double, etc.) not implement an interface like IArithmetic< T
(see below for an example)?
In isolation, neither of these limitations would be a big problem, as
we could easily work around them. However, their combination seems to
make it impossible to use generics for some tasks.

***** Discussion *****

Let us try to develop a generic Complex class in C# with generics. Our
(admitedly naive) first shot would be as follows:

public struct Complex< T >
{
T real;
T imag;

public Complex( T real, T imag )
{
this.real = real;
this.imag = imag;
}

public static Complex< T > operator +(
Complex< T > left, Complex< T > right )
{
return new Complex< T >(
left.real + right.real, left.imag + right.imag );
}

// other operators
}

Trying to compile this yields the following errors:

complex.cs(24,7): error CS0019: Operator '+' cannot be applied to
operands of type 'T' and 'T'
complex.cs(24,31): error CS0019: Operator '+' cannot be applied to
operands of type 'T' and 'T'

which is fair enough, as we didn't specify any constraints for T.
However, exactly what constraint should we specify to make this work?
After all we want to use our Complex class with primitive types (e.g.
float, double) *and* user-defined types. To make it usable for the
latter is easy enough:

public interface IArithmetic< T >
{
T Add( T other );
// other operations
}

public struct Complex< T > where T : IArithmetic< T >
{
T real;
T imag;

public Complex( T real, T imag )
{
this.real = real;
this.imag = imag;
}

public static Complex< T > operator +(
Complex< T > left, Complex< T > right )
{
return new Complex< T >(
left.real.Add( right.real ),
left.imag.Add( right.imag ) );
}

// other operators
}

So far so good, but what do we do to make this work for types that do
not implement our interface, namely framework-supplied ones like
float, double and perhaps decimal? All these types only implement the
interfaces IComparable, IFormattable, IConvertible and IComparable< T. None of these helps us implementing Complex. After some fiddling

around, I came up with the following:

public interface IArithmetic< T >
{
T Add( T other );
}

public struct Complex< T >
{
T real;
T imag;

public Complex( T real, T imag )
{
this.real = real;
this.imag = imag;
}

public static Complex< T > operator+(
Complex< T > left, Complex< T > right )
{
return new Complex< T >(
Add( left.real, right.real ),
Add( left.imag, right.imag ) );
}

// other operators

static float Add( float left, float right )
{
return left + right;
}

// other overloads for double, etc.

// overload for all other types
static U Add< U >( U left, U right )
{
// implementation postponed
}
}

I was hoping that the two Add overloads would allow me to discriminate
between primitive, framework-supplied types and user-supplied types.
This does not work, the generic overload is also selected when I add
two Complex< float > objects.
I then tried various other ways to discriminate between types, but
none of them led to anything more interesting than the above. It seems
that when you call a function with an argument of generic type that
the parameter of the function accepting said argument inevitably also
needs to be a generic type. I.e. the second Add overload can take two
forms:

static T Add( T left, T right )

or

static U Add< U >( U left, U right )

It seems that no matter which form we choose, no other Add overloads
(e.g. for float, etc.) will ever be considered.
Nov 16 '05 #1
17 3273
Andreas,
1. Why does the overload resolution mechanism only consider overloads
with generic parameters when we call a function with a generic
argument?
Because method resolution is done at compile time, but the actual
generic argument isn't known until runtime.

2. Why do .NET framework classes for primitive types (Byte, Int32,
Decimal, Double, etc.) not implement an interface like IArithmetic< T
(see below for an example)?

I don't know why. It's a fairly common request, but I don't think it
would be the best solution. What's really missing here are operator
contraints. Hopefully that's something they can add support for in
future versions of the framework.

Implementing an IArithmetic type of interface as a workaround would
have other consequences. One major problem I see with it is the fact
that casting a value type to an implemented interface requires boxing.
All that boxing would be terrible for performance if you did a
signinficant amount of calculations.

So far so good, but what do we do to make this work for types that do
not implement our interface, namely framework-supplied ones like
float, double and perhaps decimal?


If you change the IArithmetic contract so that it can be implemented
by a type separate from the type it operates on, like this

interface IArithmetic<T>
{
T Add(T left, T right);
...
}

You could write implementations for ints and doubles and such yourself
(the set of primitive value types is after all limited), and then get
the IArithmetic implementation through a factory. Something like
public struct Complex< T > where T : new()
{
T real;
T imag;
static IArithmetic<T> arith;

static Complex() {
if ( typeof(T).IsPrimitive )
arith = ArithmeticFactory.GetPrimitiveArithmetic<T>();
else if ( typeof(IArithmetic<T>).IsAssignableFrom(typeof(T)) )
arith = new T() as IArithmetic<T>;
else
throw new TypeLoadException(
"T must be primitive or implement IArithmetic<T>");
}

public static Complex< T > operator+(
Complex< T > left, Complex< T > right )
{
return new Complex< T >(
arith.Add( left.real, right.real ),
arith.Add( left.imag, right.imag ) );
}
}

static class ArithmeticFactory
{
private class Int32Arithmetic : IArithmetic<int> {
public int Add(int left, int right) { return left + right; }
}

public static IArithmethic GetPrimitiveArithmetic<T>()
{
// You could use a more efficient lookup here, and make the
// implementations singletons. This is just for demonstration
if ( typeof(T) == typeof(int) )
return (IArithmetic<T>)new Int32Arithmetic();
... and so on for other primitive types ...
}
}
This avoids the boxing overhead, but it's of course a lot more typing.
And since the IArithmetic implementation is now external to to the
operands, they can't access private instance data which may or may not
be a problem.

Mattias

--
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Nov 16 '05 #2
Hi Mattias,
1. Why does the overload resolution mechanism only consider overloads
with generic parameters when we call a function with a generic
argument?
Because method resolution is done at compile time, but the actual
generic argument isn't known until runtime.


I guess it depends what you call compile time and runtime. In .NET you
actually have two compile times: Firstly, the generic class (C#, VB, etc.)
is compiled into MSIL. Later (at runtime), the MSIL is compiled to native
code. As far as I can see, under certain circumstances, it would be possible
to postpone overload resolution for function calls involving generic
parameters until this second compilation stage.
2. Why do .NET framework classes for primitive types (Byte, Int32,
Decimal, Double, etc.) not implement an interface like IArithmetic< T
(see below for an example)?
I don't know why. It's a fairly common request, but I don't think it
would be the best solution. What's really missing here are operator
contraints. Hopefully that's something they can add support for in
future versions of the framework.


Indeed, operator constraints would be the best solution.
Implementing an IArithmetic type of interface as a workaround would
have other consequences. One major problem I see with it is the fact
that casting a value type to an implemented interface requires boxing.
All that boxing would be terrible for performance if you did a
signinficant amount of calculations.
Unless I'm mistaken the whole point of interfaces in generics is that you
don't have to pay that boxing overhead. The interface is only there to
ensure that your type meets certain requirements. The generic code then
directly deals with objects of the type it was instantiated with and never
ever has to box anything.
So far so good, but what do we do to make this work for types that do
not implement our interface, namely framework-supplied ones like
float, double and perhaps decimal?


If you change the IArithmetic contract so that it can be implemented
by a type separate from the type it operates on, like this

interface IArithmetic<T>
{
T Add(T left, T right);
...
}

You could write implementations for ints and doubles and such yourself
(the set of primitive value types is after all limited), and then get
the IArithmetic implementation through a factory. Something like

<code snipped>
This avoids the boxing overhead, but it's of course a lot more typing.
And since the IArithmetic implementation is now external to to the
operands, they can't access private instance data which may or may not
be a problem.


Ok, I forgot to mention why I want to use generics for a hypothetical
Complex/Matrix library. One of the main reasons is to achieve performance
that is at least comparable with C++. I believe this won't be possible if we
runtime dispatch for each operation on Complex/Matrix elements.

Regards,

Andreas

Nov 16 '05 #3
Mattias,
All that boxing would be terrible for performance if you did a
signinficant amount of calculations.
I've found when I use IComparable<T> for a value type (System.Int32 for
example), there is no boxing going on, why would IArithmetic<T> cause boxing
to go on?

As Andreas states, is not that the whole point of the IComparable<T>
interface? to avoid boxing!

I agree true operator constraints would probably be the best, Not entirely
sure how they would work as + on Int32 is a IL opcode, while + on
System.Decimal is an overloaded operator, would an operator contraint
require an overloaded operator, requiring Int32 to offer the overloaded
operators, although + for Int32 is already an IL opcode?

I don't see why IArithmetic<T> could not be easily implemented today... (I'm
sure there are reasons ;-)

I had not thought using a Factory method like that: My thought, if I needed
IArithmetic<T> was to create proxy classes for type built-in types similar
to the System.Data.SqlTypes types, my class would have the IArithmetic<T>
constraint, but you would pass it a ArithmeticInt32 instead of an Int32.

interface IArithmetic<T>
{
T Add(T other);
...
}

struct ArithmeticInt32 : IArithmetic<Int32>
{
Int32 value;

Int32 Add(Int32 other)
{
return value + other;
}

...

// implicit conversions possibly
}

struct ArithmeticDouble : IArithmetic<Double> {...}

public struct Complex<T> : where T : Arithmetic<T>
{
}

Complex<ArithmeticInt32> ci;
Complex<ArithmeticDouble> cd;

Of course Complex<T> would possible implement IArithmetic<T> also for
itself....

My only concern with IArithmetic<T> is should there be a single interface
with all math "operators", or should there be individual interfaces, such as
IAdd<T>, ISubtract<T>, IMultiply<T>, IDivide<T>, and so on that
IArithmetic<T> inherits from? As I can see creating generic classes that
need to support addition but (TimeSpan) but Multiplication does not make
sense...

Just a thought
Jay

"Mattias Sjögren" <ma********************@mvps.org> wrote in message
news:%2****************@TK2MSFTNGP10.phx.gbl... Andreas,
1. Why does the overload resolution mechanism only consider overloads
with generic parameters when we call a function with a generic
argument?


Because method resolution is done at compile time, but the actual
generic argument isn't known until runtime.

2. Why do .NET framework classes for primitive types (Byte, Int32,
Decimal, Double, etc.) not implement an interface like IArithmetic< T
(see below for an example)?


I don't know why. It's a fairly common request, but I don't think it
would be the best solution. What's really missing here are operator
contraints. Hopefully that's something they can add support for in
future versions of the framework.

Implementing an IArithmetic type of interface as a workaround would
have other consequences. One major problem I see with it is the fact
that casting a value type to an implemented interface requires boxing.
All that boxing would be terrible for performance if you did a
signinficant amount of calculations.

So far so good, but what do we do to make this work for types that do
not implement our interface, namely framework-supplied ones like
float, double and perhaps decimal?


If you change the IArithmetic contract so that it can be implemented
by a type separate from the type it operates on, like this

interface IArithmetic<T>
{
T Add(T left, T right);
...
}

You could write implementations for ints and doubles and such yourself
(the set of primitive value types is after all limited), and then get
the IArithmetic implementation through a factory. Something like
public struct Complex< T > where T : new()
{
T real;
T imag;
static IArithmetic<T> arith;

static Complex() {
if ( typeof(T).IsPrimitive )
arith = ArithmeticFactory.GetPrimitiveArithmetic<T>();
else if ( typeof(IArithmetic<T>).IsAssignableFrom(typeof(T)) )
arith = new T() as IArithmetic<T>;
else
throw new TypeLoadException(
"T must be primitive or implement IArithmetic<T>");
}

public static Complex< T > operator+(
Complex< T > left, Complex< T > right )
{
return new Complex< T >(
arith.Add( left.real, right.real ),
arith.Add( left.imag, right.imag ) );
}
}

static class ArithmeticFactory
{
private class Int32Arithmetic : IArithmetic<int> {
public int Add(int left, int right) { return left + right; }
}

public static IArithmethic GetPrimitiveArithmetic<T>()
{
// You could use a more efficient lookup here, and make the
// implementations singletons. This is just for demonstration
if ( typeof(T) == typeof(int) )
return (IArithmetic<T>)new Int32Arithmetic();
... and so on for other primitive types ...
}
}
This avoids the boxing overhead, but it's of course a lot more typing.
And since the IArithmetic implementation is now external to to the
operands, they can't access private instance data which may or may not
be a problem.

Mattias

--
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.

Nov 16 '05 #4
Doh!
struct ArithmeticInt32 : IArithmetic<Int32>
should be
struct ArithmeticInt32 : IArithmetic<ArithmeticInt32>
Jay

"Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> wrote in message
news:%2******************@TK2MSFTNGP10.phx.gbl... Mattias,
All that boxing would be terrible for performance if you did a
signinficant amount of calculations.
I've found when I use IComparable<T> for a value type (System.Int32 for
example), there is no boxing going on, why would IArithmetic<T> cause

boxing to go on?

As Andreas states, is not that the whole point of the IComparable<T>
interface? to avoid boxing!

I agree true operator constraints would probably be the best, Not entirely
sure how they would work as + on Int32 is a IL opcode, while + on
System.Decimal is an overloaded operator, would an operator contraint
require an overloaded operator, requiring Int32 to offer the overloaded
operators, although + for Int32 is already an IL opcode?

I don't see why IArithmetic<T> could not be easily implemented today... (I'm sure there are reasons ;-)

I had not thought using a Factory method like that: My thought, if I needed IArithmetic<T> was to create proxy classes for type built-in types similar
to the System.Data.SqlTypes types, my class would have the IArithmetic<T>
constraint, but you would pass it a ArithmeticInt32 instead of an Int32.

interface IArithmetic<T>
{
T Add(T other);
...
}

struct ArithmeticInt32 : IArithmetic<Int32>
{
Int32 value;

Int32 Add(Int32 other)
{
return value + other;
}

...

// implicit conversions possibly
}

struct ArithmeticDouble : IArithmetic<Double> {...}

public struct Complex<T> : where T : Arithmetic<T>
{
}

Complex<ArithmeticInt32> ci;
Complex<ArithmeticDouble> cd;

Of course Complex<T> would possible implement IArithmetic<T> also for
itself....

My only concern with IArithmetic<T> is should there be a single interface
with all math "operators", or should there be individual interfaces, such as IAdd<T>, ISubtract<T>, IMultiply<T>, IDivide<T>, and so on that
IArithmetic<T> inherits from? As I can see creating generic classes that
need to support addition but (TimeSpan) but Multiplication does not make
sense...

Just a thought
Jay

"Mattias Sjögren" <ma********************@mvps.org> wrote in message
news:%2****************@TK2MSFTNGP10.phx.gbl...
Andreas,
1. Why does the overload resolution mechanism only consider overloads
with generic parameters when we call a function with a generic
argument?


Because method resolution is done at compile time, but the actual
generic argument isn't known until runtime.

2. Why do .NET framework classes for primitive types (Byte, Int32,
Decimal, Double, etc.) not implement an interface like IArithmetic< T
> (see below for an example)?


I don't know why. It's a fairly common request, but I don't think it
would be the best solution. What's really missing here are operator
contraints. Hopefully that's something they can add support for in
future versions of the framework.

Implementing an IArithmetic type of interface as a workaround would
have other consequences. One major problem I see with it is the fact
that casting a value type to an implemented interface requires boxing.
All that boxing would be terrible for performance if you did a
signinficant amount of calculations.

So far so good, but what do we do to make this work for types that do
not implement our interface, namely framework-supplied ones like
float, double and perhaps decimal?


If you change the IArithmetic contract so that it can be implemented
by a type separate from the type it operates on, like this

interface IArithmetic<T>
{
T Add(T left, T right);
...
}

You could write implementations for ints and doubles and such yourself
(the set of primitive value types is after all limited), and then get
the IArithmetic implementation through a factory. Something like
public struct Complex< T > where T : new()
{
T real;
T imag;
static IArithmetic<T> arith;

static Complex() {
if ( typeof(T).IsPrimitive )
arith = ArithmeticFactory.GetPrimitiveArithmetic<T>();
else if ( typeof(IArithmetic<T>).IsAssignableFrom(typeof(T)) )
arith = new T() as IArithmetic<T>;
else
throw new TypeLoadException(
"T must be primitive or implement IArithmetic<T>");
}

public static Complex< T > operator+(
Complex< T > left, Complex< T > right )
{
return new Complex< T >(
arith.Add( left.real, right.real ),
arith.Add( left.imag, right.imag ) );
}
}

static class ArithmeticFactory
{
private class Int32Arithmetic : IArithmetic<int> {
public int Add(int left, int right) { return left + right; }
}

public static IArithmethic GetPrimitiveArithmetic<T>()
{
// You could use a more efficient lookup here, and make the
// implementations singletons. This is just for demonstration
if ( typeof(T) == typeof(int) )
return (IArithmetic<T>)new Int32Arithmetic();
... and so on for other primitive types ...
}
}
This avoids the boxing overhead, but it's of course a lot more typing.
And since the IArithmetic implementation is now external to to the
operands, they can't access private instance data which may or may not
be a problem.

Mattias

--
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.


Nov 16 '05 #5
Hi Jay,

Jay B. Harlow [MVP - Outlook] wrote:
I had not thought using a Factory method like that: My thought, if I
needed IArithmetic<T> was to create proxy classes for type built-in
types similar to the System.Data.SqlTypes types, my class would have
the IArithmetic<T> constraint, but you would pass it a
ArithmeticInt32 instead of an Int32. [code snipped]

Implementing proxies is of course always an option but I think it is a
really bad one. After all generics should help us to reduce the amount of
code, not force us to produce more of it!
My only concern with IArithmetic<T> is should there be a single
interface with all math "operators", or should there be individual
interfaces,


Agreed, IArithmetic< T > would be too inflexible. So, operator constraints
would probably be the best solution.

Regards,

Andreas

Nov 16 '05 #6
Andreas,
Implementing proxies is of course always an option but I think it is a
really bad one. I sincerely hope you did not mean "really bad one" as bad as it sounds. :-|

I agree its not necessarily a good option. However! In light of not having
Operator constraints and the base types (Int32) not supporting an
IArithmetic<T> directly, I find it a reasonable good workaround.

I would love to hear a "better" work around, that can implemented today, as
I have a couple of places where doing math generically would be useful...

A second alternative I've wondered how usable would be Generic Delegates,
only I'm not sure how easy they would be to use in this case.

Action<T> is an example of a generic delegate:
http://lab.msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/T_System_Action`1.asp

Just a thought
Jay

"Andreas Huber" <ah****@gmx.net> wrote in message
news:40**********@news.bluewin.ch... Hi Jay,

Jay B. Harlow [MVP - Outlook] wrote:
I had not thought using a Factory method like that: My thought, if I
needed IArithmetic<T> was to create proxy classes for type built-in
types similar to the System.Data.SqlTypes types, my class would have
the IArithmetic<T> constraint, but you would pass it a
ArithmeticInt32 instead of an Int32.

[code snipped]

Implementing proxies is of course always an option but I think it is a
really bad one. After all generics should help us to reduce the amount of
code, not force us to produce more of it!
My only concern with IArithmetic<T> is should there be a single
interface with all math "operators", or should there be individual
interfaces,


Agreed, IArithmetic< T > would be too inflexible. So, operator constraints
would probably be the best solution.

Regards,

Andreas

Nov 16 '05 #7

"Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> wrote in message
news:Op*************@TK2MSFTNGP12.phx.gbl...
Andreas,
Implementing proxies is of course always an option but I think it is a
really bad one.

I sincerely hope you did not mean "really bad one" as bad as it sounds.
:-|

I agree its not necessarily a good option. However! In light of not having
Operator constraints and the base types (Int32) not supporting an
IArithmetic<T> directly, I find it a reasonable good workaround.

I would love to hear a "better" work around, that can implemented today,
as
I have a couple of places where doing math generically would be useful...

A second alternative I've wondered how usable would be Generic Delegates,
only I'm not sure how easy they would be to use in this case.\


Well, you *could* use dynamic methods, assuming you have the permissions:
public delegate T Operator<T>(T a,T b);
public static Operator<T> CreateAddOperator<T>()
{
DynamicMethod method = new DynamicMethod("AddMethod" +
typeof(T).ToString(), typeof(T), new Type[] { typeof(T), typeof(T) },
typeof(OperatorFactory));
ILGenerator ilg = method.GetILGenerator();
ilg.Emit(OpCodes.Ldarg_0);
ilg.Emit(OpCodes.Ldarg_1);
if (typeof(T).IsPrimitive)
{

ilg.Emit(OpCodes.Add);

}
else
{
//do reflection on typeof(T) and generate op_Add code.
MethodInfo info = typeof(T).GetMethod("op_Addition", new Type[] {
typeof(T), typeof(T) }, null);
ilg.EmitCall(OpCodes.Call, info, null);
}
ilg.Emit(OpCodes.Ret);

return (Operator<T>)method.CreateDelegate(typeof(Operator <T>));
}

I've only tested int and decimal, but it does work for those two. This
doesn't handle multiple add types(although you could write one). The biggest
problem is DynamicMethods have some permission requirements and my not be
emittable in some situations. I'm not sure how the security works with
regards to them however.
Nov 16 '05 #8
> I sincerely hope you did not mean "really bad one" as bad as it
sounds. :-|
Sorry, that was not my intention. I didn't write "really bad" because I
think it's a bad idea to solve the problem this way (under the
circumstances, it might even be the best way). I wrote it because I had high
hopes that .NET generics will be a powerful tool to design our programs
better and avoid most of the code duplication that's currently necessary.
I'm a bit disappointed to see that I was hoping for too much. Generics do
solve a few problems (namely performance and compile-time correctness stuff)
but they still only partially solve that nasty code duplication problem. I
also think the guys at Microsoft must be aware of this but they did not do
something about it. I'm sure they have their reasons but it would be nice to
know them (including easy work-arounds we might be missing).
A second alternative I've wondered how usable would be Generic
Delegates,
only I'm not sure how easy they would be to use in this case.

Action<T> is an example of a generic delegate:

http://lab.msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/T_System_Action`1.asp

Generic delegates might indeed offer a way to specify how to perform the
operations of the generic type. But then again the same can be done with an
interface:

interface IArithmeticOps< T >
{
T Add( T left, T right );
// other ops
}

struct Complex< T, Ops > where U : IArithmeticOps< T >, new()
{
static Ops ops = new Ops();
T real;
T imag;

// ...

public static T operator+( T left, T right )
{
return new Complex< T, Ops >(
ops.Add( left.real, right.real ),
ops.Add( left.imag, right.imag ) );
}
}

Regards,

Andreas

Nov 16 '05 #9
Daniel,
Maybe its late ;-)

By the time I write all the dynamic methods for all the types I would want,
wouldn't it be quicker or at least just as easy to simply write a code
generator based on the CodeDom to spit out all the Arithmetic proxy classes
based on what I stated??

Otherwise I'm keeping the code snippet it may come in handy for other
things...

Jay

"Daniel O'Connell [C# MVP]" <onyxkirx@--NOSPAM--comcast.net> wrote in
message news:OR**************@TK2MSFTNGP11.phx.gbl...

"Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> wrote in message
news:Op*************@TK2MSFTNGP12.phx.gbl...
Andreas,
Implementing proxies is of course always an option but I think it is a
really bad one. I sincerely hope you did not mean "really bad one" as bad as it sounds.
:-|

I agree its not necessarily a good option. However! In light of not having Operator constraints and the base types (Int32) not supporting an
IArithmetic<T> directly, I find it a reasonable good workaround.

I would love to hear a "better" work around, that can implemented today,
as
I have a couple of places where doing math generically would be useful...
A second alternative I've wondered how usable would be Generic Delegates, only I'm not sure how easy they would be to use in this case.\


Well, you *could* use dynamic methods, assuming you have the permissions:
public delegate T Operator<T>(T a,T b);
public static Operator<T> CreateAddOperator<T>()
{
DynamicMethod method = new DynamicMethod("AddMethod" +
typeof(T).ToString(), typeof(T), new Type[] { typeof(T), typeof(T) },
typeof(OperatorFactory));
ILGenerator ilg = method.GetILGenerator();
ilg.Emit(OpCodes.Ldarg_0);
ilg.Emit(OpCodes.Ldarg_1);
if (typeof(T).IsPrimitive)
{

ilg.Emit(OpCodes.Add);

}
else
{
//do reflection on typeof(T) and generate op_Add code.
MethodInfo info = typeof(T).GetMethod("op_Addition", new Type[] {
typeof(T), typeof(T) }, null);
ilg.EmitCall(OpCodes.Call, info, null);
}
ilg.Emit(OpCodes.Ret);

return (Operator<T>)method.CreateDelegate(typeof(Operator <T>));
}

I've only tested int and decimal, but it does work for those two. This
doesn't handle multiple add types(although you could write one). The

biggest problem is DynamicMethods have some permission requirements and my not be
emittable in some situations. I'm not sure how the security works with
regards to them however.

Nov 16 '05 #10

"Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> wrote in message
news:uA**************@TK2MSFTNGP10.phx.gbl...
Daniel,
Maybe its late ;-)

By the time I write all the dynamic methods for all the types I would
want,
wouldn't it be quicker or at least just as easy to simply write a code
generator based on the CodeDom to spit out all the Arithmetic proxy
classes
based on what I stated??

Probably, ;). Its all a matter of what you need and want to subject your
users to. Personally I'd take the approach that *doesn't* use extra
interfaces externally if possible. It'll confuse less people and put less
strain on existing OM's.

The only issue is, the CodeDom approach won't support extra types, the
dynamic methods approach will work with *all* types that support the
operator in question, even if they are written by the end user. CodeDom is a
bit tricky there.
Granted, the CodeDom approach gives you a nice way to constrain types.

It ends up being whichever best supports your needs.
Otherwise I'm keeping the code snippet it may come in handy for other
things...


Hopefully it will. Dynamic Methods are probably my favorite things about
..NET 2.0, ;).
Nov 16 '05 #11
Andreas,
If you haven't you may want to submit a suggestion at:

http://lab.msdn.microsoft.com/vs2005/

I see at least one suggestion:

http://lab.msdn.microsoft.com/produc...5-9c64cce45d2a

Related to this problem.

I was actually thinking of the Generic Delegate combined with an anonymous
method on possible the constructor...

Hope this helps
Jay
"Andreas Huber" <ah****@gmx.net> wrote in message
news:40**********@news.bluewin.ch...
I sincerely hope you did not mean "really bad one" as bad as it
sounds. :-|
Sorry, that was not my intention. I didn't write "really bad" because I
think it's a bad idea to solve the problem this way (under the
circumstances, it might even be the best way). I wrote it because I had

high hopes that .NET generics will be a powerful tool to design our programs
better and avoid most of the code duplication that's currently necessary.
I'm a bit disappointed to see that I was hoping for too much. Generics do
solve a few problems (namely performance and compile-time correctness stuff) but they still only partially solve that nasty code duplication problem. I
also think the guys at Microsoft must be aware of this but they did not do
something about it. I'm sure they have their reasons but it would be nice to know them (including easy work-arounds we might be missing).
A second alternative I've wondered how usable would be Generic
Delegates,
only I'm not sure how easy they would be to use in this case.

Action<T> is an example of a generic delegate:

http://lab.msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/T_System_Action`1.asp
Generic delegates might indeed offer a way to specify how to perform the
operations of the generic type. But then again the same can be done with an interface:

interface IArithmeticOps< T >
{
T Add( T left, T right );
// other ops
}

struct Complex< T, Ops > where U : IArithmeticOps< T >, new()
{
static Ops ops = new Ops();
T real;
T imag;

// ...

public static T operator+( T left, T right )
{
return new Complex< T, Ops >(
ops.Add( left.real, right.real ),
ops.Add( left.imag, right.imag ) );
}
}

Regards,

Andreas

Nov 16 '05 #12

"Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> wrote in message
news:Oo**************@TK2MSFTNGP12.phx.gbl...
Andreas,
If you haven't you may want to submit a suggestion at:

http://lab.msdn.microsoft.com/vs2005/

I see at least one suggestion:

http://lab.msdn.microsoft.com/produc...5-9c64cce45d2a


Unfortunatly that solution is pretty much *entirely* against the semantics
of C# as it stands today. Sadly, I think an entire virtual operator
implementation would have to be added to get this to work in any way nearing
clean.
Operators are rather complex things. Many suggetsions I see for adding
operator support are designed thinking that
Class<T> where T : operator+
is sufficent.

Its not. You need
Class<T> where T : T operator+(T,T)

at the minimum. And that *still* doesn't deal with issues like int and long,
which don't actually overload any operators.

This is really a situation where you are just screwed. IArithmetic would
probably be better. It doesn't require language changes across the board,
just a change to the system valuetypes, which can pretty much be done
without adding anything new to any language and it does so in a half way
sensible way with regard to existing language rules.
Nov 16 '05 #13
Daniel,
I gave the link more for an example of an existing suggestion, not as a
suggestion I specifically endorse.

I like IArithmetic<T>, as it seems to be the "easier" route. (the KISS
principal). If only Int32 implemented it ;-) also IArithmetic<T> is in
keeping with IComparable<T>.

I agree that an actual "operator +" constraint may need to get too fancy to
be useful, especially when you consider it needs to work across languages.
But then again Microsoft has a lot of talented people working for them, and
if we (the users) keep throwing it about in the publics, hopefully something
usable can be created...

Hopefully we can see something usable included in .NET 2.0 to allow generic
arithmetic...

Jay
"Daniel O'Connell [C# MVP]" <onyxkirx@--NOSPAM--comcast.net> wrote in
message news:%2****************@tk2msftngp13.phx.gbl...

"Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> wrote in message
news:Oo**************@TK2MSFTNGP12.phx.gbl...
Andreas,
If you haven't you may want to submit a suggestion at:

http://lab.msdn.microsoft.com/vs2005/

I see at least one suggestion:
http://lab.msdn.microsoft.com/produc...5-9c64cce45d2a
Unfortunatly that solution is pretty much *entirely* against the semantics
of C# as it stands today. Sadly, I think an entire virtual operator
implementation would have to be added to get this to work in any way nearing clean.
Operators are rather complex things. Many suggetsions I see for adding
operator support are designed thinking that
Class<T> where T : operator+
is sufficent.

Its not. You need
Class<T> where T : T operator+(T,T)

at the minimum. And that *still* doesn't deal with issues like int and long, which don't actually overload any operators.

This is really a situation where you are just screwed. IArithmetic would
probably be better. It doesn't require language changes across the board,
just a change to the system valuetypes, which can pretty much be done
without adding anything new to any language and it does so in a half way
sensible way with regard to existing language rules.

Nov 16 '05 #14

"Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> wrote in message
news:%2****************@TK2MSFTNGP11.phx.gbl...
Daniel,
I gave the link more for an example of an existing suggestion, not as a
suggestion I specifically endorse.

Sorry, I didn't mean to be harsh. I'm just rather annoyed with the operator
thing. I think I've posted that same general reply a dozen times now.
I like IArithmetic<T>, as it seems to be the "easier" route. (the KISS
principal). If only Int32 implemented it ;-) also IArithmetic<T> is in
keeping with IComparable<T>. Ya, that would help termendously by helping to constrain generics to
primatives alone. I do wish there was a way to express that you want int,
uint, byte, sbyte, short, ushort, long, ulong, string, decimal, double or
float *only* in a generic. It'd help out *alot* in data situations where you
want to create classes that handle simple data. But, alas, that is a pipe
dream right now. IArithmetic wouldn't help with everything, but it'd make
numbers simpler.

I agree that an actual "operator +" constraint may need to get too fancy
to
be useful, especially when you consider it needs to work across languages.
But then again Microsoft has a lot of talented people working for them,
and
if we (the users) keep throwing it about in the publics, hopefully
something
usable can be created...

Well, I for one am not a huge fan of operator overloading in general, but it
is frustrating not to be able to perform basic mathematics with generics. It
certainly takes away the ability to *easily* do something like the stream in
STL, where the size type could be defined in the template.


Nov 16 '05 #15
I've found when I use IComparable<T> for a value type (System.Int32 for
example), there is no boxing going on, why would IArithmetic<T> cause boxing
to go on?
Right, it shouldn't, by bad. Casting to the interfce still causes
boxing, but there shouldn't be any need for the cast if the constraint
is there.

I agree true operator constraints would probably be the best, Not entirely
sure how they would work as + on Int32 is a IL opcode, while + on
System.Decimal is an overloaded operator, would an operator contraint
require an overloaded operator, requiring Int32 to offer the overloaded
operators, although + for Int32 is already an IL opcode?
I don't know how they'd implement it. The compilers might have to
special-case the primitive types.

Either way, the JIT better be darn good at recognizing the IL sequence
and effectively produce the same native code as a simple add
instruction for primitive types, or the overhead of the method call
would hurt performance. The same is true for IArithmetic methods of
course.

My only concern with IArithmetic<T> is should there be a single interface
with all math "operators", or should there be individual interfaces, such as
IAdd<T>, ISubtract<T>, IMultiply<T>, IDivide<T>, and so on that
IArithmetic<T> inherits from? As I can see creating generic classes that
need to support addition but (TimeSpan) but Multiplication does not make
sense...


Yes that's definitely a problem too. A single interface with all the
operations is not granular enough, and wouldn't give you compile time
checking of which methods are actually supported.

Mattias

--
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Nov 16 '05 #16
Daniel,
primatives alone. I do wish there was a way to express that you want int,
uint, byte, sbyte, short, ushort, long, ulong, string, decimal, double or
float *only* in a generic Why? What if I create a BetterInt32? (aka a family of types like SqlInt32 in
System.Data.SqlTypes) that due to CLS requirements BetterInt32 cannot be a
generic class, so I need to do it the "old fashion way". Remember that
Generics are not CLS compatible, however you are free to use generics
internal to your project, even if the public interface is CLS compatible.

Why should generic math be limited to Int32 and not my BetterInt32?

Also as I mentioned elsewhere in this thread. int uses an IL opcode for
addition, while decimal uses an overloaded operator, so you have an
exception from the start, so enabling a constraint for just the "primitives"
is probably more work then it needs to be or should be, as it would need to
support both overloaded operators & opcodes...

One of the reasons for struct & overloaded operators is to enable us as
designers to define our own "simple data". For example Martin Fowler's
Range & Quantity patterns, both of which I would consider "simple data", and
I could see a need to enable them for generic math!

http://www.martinfowler.com/ap2/

http://martinfowler.com/ieeeSoftware/whenType.pdf

Just a thought
Jay

"Daniel O'Connell [C# MVP]" <onyxkirx@--NOSPAM--comcast.net> wrote in
message news:OA****************@TK2MSFTNGP10.phx.gbl...
"Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> wrote in message
news:%2****************@TK2MSFTNGP11.phx.gbl...
Daniel,
I gave the link more for an example of an existing suggestion, not as a
suggestion I specifically endorse.

Sorry, I didn't mean to be harsh. I'm just rather annoyed with the

operator thing. I think I've posted that same general reply a dozen times now.
I like IArithmetic<T>, as it seems to be the "easier" route. (the KISS
principal). If only Int32 implemented it ;-) also IArithmetic<T> is in
keeping with IComparable<T>. Ya, that would help termendously by helping to constrain generics to
primatives alone. I do wish there was a way to express that you want int,
uint, byte, sbyte, short, ushort, long, ulong, string, decimal, double or
float *only* in a generic. It'd help out *alot* in data situations where

you want to create classes that handle simple data. But, alas, that is a pipe
dream right now. IArithmetic wouldn't help with everything, but it'd make
numbers simpler.

I agree that an actual "operator +" constraint may need to get too fancy
to
be useful, especially when you consider it needs to work across languages. But then again Microsoft has a lot of talented people working for them,
and
if we (the users) keep throwing it about in the publics, hopefully
something
usable can be created...
Well, I for one am not a huge fan of operator overloading in general, but

it is frustrating not to be able to perform basic mathematics with generics. It certainly takes away the ability to *easily* do something like the stream in STL, where the size type could be defined in the template.

Nov 16 '05 #17

"Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> wrote in message
news:eV**************@TK2MSFTNGP09.phx.gbl...
Daniel,
primatives alone. I do wish there was a way to express that you want
int,
uint, byte, sbyte, short, ushort, long, ulong, string, decimal, double or
float *only* in a generic Why? What if I create a BetterInt32? (aka a family of types like SqlInt32
in
System.Data.SqlTypes) that due to CLS requirements BetterInt32 cannot be a
generic class, so I need to do it the "old fashion way". Remember that
Generics are not CLS compatible, however you are free to use generics
internal to your project, even if the public interface is CLS compatible.

Why should generic math be limited to Int32 and not my BetterInt32?

I didn't *say* generic math. I said data. I write quite a few classes that
have to deal with simple data and often that data has to be interconverted
or expressed in an exceedingly simple type systems(no lists, no currency, no
custom value types, etc). I use IConvertible now and do my best to convert
bad types into valid ones, but its not the most reliable and clear method
possible.

Infact one of those links makes the point" "If you have a method that
expects to take a currency parameter, you can communicate this more clearly
by having a currency type and using it in the method declaration". I would
say it would follow that if your method cannot take BetterInt32, it isn't a
good idea to *allow* that method to take a BetterInt32, wouldn't you? Hence
a need to constrain to primative types when only primative types work.
Also as I mentioned elsewhere in this thread. int uses an IL opcode for
addition, while decimal uses an overloaded operator, so you have an
exception from the start, so enabling a constraint for just the
"primitives"
is probably more work then it needs to be or should be, as it would need
to
support both overloaded operators & opcodes...

One of the reasons for struct & overloaded operators is to enable us as
designers to define our own "simple data". For example Martin Fowler's
Range & Quantity patterns, both of which I would consider "simple data",
and
I could see a need to enable them for generic math!

http://www.martinfowler.com/ap2/

http://martinfowler.com/ieeeSoftware/whenType.pdf

Just a thought
Jay

"Daniel O'Connell [C# MVP]" <onyxkirx@--NOSPAM--comcast.net> wrote in
message news:OA****************@TK2MSFTNGP10.phx.gbl...

"Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> wrote in message
news:%2****************@TK2MSFTNGP11.phx.gbl...
> Daniel,
> I gave the link more for an example of an existing suggestion, not as a
> suggestion I specifically endorse.
>


Sorry, I didn't mean to be harsh. I'm just rather annoyed with the

operator
thing. I think I've posted that same general reply a dozen times now.
> I like IArithmetic<T>, as it seems to be the "easier" route. (the KISS
> principal). If only Int32 implemented it ;-) also IArithmetic<T> is in
> keeping with IComparable<T>.

Ya, that would help termendously by helping to constrain generics to
primatives alone. I do wish there was a way to express that you want
int,
uint, byte, sbyte, short, ushort, long, ulong, string, decimal, double or
float *only* in a generic. It'd help out *alot* in data situations where

you
want to create classes that handle simple data. But, alas, that is a pipe
dream right now. IArithmetic wouldn't help with everything, but it'd make
numbers simpler.
>
> I agree that an actual "operator +" constraint may need to get too
> fancy
> to
> be useful, especially when you consider it needs to work across languages. > But then again Microsoft has a lot of talented people working for them,
> and
> if we (the users) keep throwing it about in the publics, hopefully
> something
> usable can be created...
>

Well, I for one am not a huge fan of operator overloading in general, but

it
is frustrating not to be able to perform basic mathematics with generics.

It
certainly takes away the ability to *easily* do something like the stream

in
STL, where the size type could be defined in the template.


Nov 16 '05 #18

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

11
by: andrew queisser | last post by:
I've read some material on the upcoming Generics for C#. I've seen two types of syntax used for constraints: - direct specification of the interface in the angle brackets - where clauses I...
2
by: Marc | last post by:
Given a class 'Invoice' with a property 'public IMyColl<IInvoiceLine> InvoiceLines' where 'IMyColl<T> : IList<T>' i would like to detect by reflection that 'InvoiceLines' is a...
12
by: Michael S | last post by:
Why do people spend so much time writing complex generic types? for fun? to learn? for use? I think of generics like I do about operator overloading. Great to have as a language-feature, as...
1
by: Ole Nielsby | last post by:
I'm puzzled at how static fields intersect with generics, as the following snippet illustrates. namespace MonkeyParty { abstract class Fruit { } class Apple : Fruit { } class Pear : Fruit {...
1
by: Vladimir Shiryaev | last post by:
Hello! Exception handling in generics seems to be a bit inconsistent to me. Imagine, I have "MyOwnException" class derived from "ApplicationException". I also have two classes...
4
by: Cedric Rogers | last post by:
I wasn't sure if I could do this. I believe I am stretching the capability of what generics can do for me but here goes. I have a generic delegate defined as public delegate bool...
7
by: SpotNet | last post by:
Hello NewsGroup, Reading up on Generics in the .NET Framework 2.0 using C# 2005 (SP1), I have a question on the application of Generics. Knowingly, Generic classes are contained in the...
4
by: ludwig.stuyck | last post by:
Hello, I updated my article on generics with databinding and serialization/ deserialization. Summary: Generics are one of the most useful improvements in the .NET 2.0 framework. In this...
6
by: CassioT | last post by:
Hi. I want to create a base form class with a generic parameter. public BaseForm<T: Form {} public MyForm : BaseForm<MyType> {} The problem here is that the inherited form doesn't work in...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.