473,739 Members | 11,435 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

.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,3 1): 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 3321
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).IsPri mitive )
arith = ArithmeticFacto ry.GetPrimitive Arithmetic<T>() ;
else if ( typeof(IArithme tic<T>).IsAssig nableFrom(typeo f(T)) )
arith = new T() as IArithmetic<T>;
else
throw new TypeLoadExcepti on(
"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 ArithmeticFacto ry
{
private class Int32Arithmetic : IArithmetic<int > {
public int Add(int left, int right) { return left + right; }
}

public static IArithmethic GetPrimitiveAri thmetic<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.Sql Types 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<Int 32>
{
Int32 value;

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

...

// implicit conversions possibly
}

struct ArithmeticDoubl e : IArithmetic<Dou ble> {...}

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

Complex<Arithme ticInt32> ci;
Complex<Arithme ticDouble> 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.o rg> wrote in message
news:%2******** ********@TK2MSF TNGP10.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).IsPri mitive )
arith = ArithmeticFacto ry.GetPrimitive Arithmetic<T>() ;
else if ( typeof(IArithme tic<T>).IsAssig nableFrom(typeo f(T)) )
arith = new T() as IArithmetic<T>;
else
throw new TypeLoadExcepti on(
"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 ArithmeticFacto ry
{
private class Int32Arithmetic : IArithmetic<int > {
public int Add(int left, int right) { return left + right; }
}

public static IArithmethic GetPrimitiveAri thmetic<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<Int 32>
should be
struct ArithmeticInt32 : IArithmetic<Ari thmeticInt32>
Jay

"Jay B. Harlow [MVP - Outlook]" <Ja************ @msn.com> wrote in message
news:%2******** **********@TK2M SFTNGP10.phx.gb l... 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.Sql Types 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<Int 32>
{
Int32 value;

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

...

// implicit conversions possibly
}

struct ArithmeticDoubl e : IArithmetic<Dou ble> {...}

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

Complex<Arithme ticInt32> ci;
Complex<Arithme ticDouble> 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.o rg> wrote in message
news:%2******** ********@TK2MSF TNGP10.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).IsPri mitive )
arith = ArithmeticFacto ry.GetPrimitive Arithmetic<T>() ;
else if ( typeof(IArithme tic<T>).IsAssig nableFrom(typeo f(T)) )
arith = new T() as IArithmetic<T>;
else
throw new TypeLoadExcepti on(
"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 ArithmeticFacto ry
{
private class Int32Arithmetic : IArithmetic<int > {
public int Add(int left, int right) { return left + right; }
}

public static IArithmethic GetPrimitiveAri thmetic<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.Sql Types 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.micros oft.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.Sql Types 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******** *****@TK2MSFTNG P12.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> CreateAddOperat or<T>()
{
DynamicMethod method = new DynamicMethod(" AddMethod" +
typeof(T).ToStr ing(), typeof(T), new Type[] { typeof(T), typeof(T) },
typeof(Operator Factory));
ILGenerator ilg = method.GetILGen erator();
ilg.Emit(OpCode s.Ldarg_0);
ilg.Emit(OpCode s.Ldarg_1);
if (typeof(T).IsPr imitive)
{

ilg.Emit(OpCode s.Add);

}
else
{
//do reflection on typeof(T) and generate op_Add code.
MethodInfo info = typeof(T).GetMe thod("op_Additi on", new Type[] {
typeof(T), typeof(T) }, null);
ilg.EmitCall(Op Codes.Call, info, null);
}
ilg.Emit(OpCode s.Ret);

return (Operator<T>)me thod.CreateDele gate(typeof(Ope rator<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.micros oft.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******** ******@TK2MSFTN GP11.phx.gbl...

"Jay B. Harlow [MVP - Outlook]" <Ja************ @msn.com> wrote in message
news:Op******** *****@TK2MSFTNG P12.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> CreateAddOperat or<T>()
{
DynamicMethod method = new DynamicMethod(" AddMethod" +
typeof(T).ToStr ing(), typeof(T), new Type[] { typeof(T), typeof(T) },
typeof(Operator Factory));
ILGenerator ilg = method.GetILGen erator();
ilg.Emit(OpCode s.Ldarg_0);
ilg.Emit(OpCode s.Ldarg_1);
if (typeof(T).IsPr imitive)
{

ilg.Emit(OpCode s.Add);

}
else
{
//do reflection on typeof(T) and generate op_Add code.
MethodInfo info = typeof(T).GetMe thod("op_Additi on", new Type[] {
typeof(T), typeof(T) }, null);
ilg.EmitCall(Op Codes.Call, info, null);
}
ilg.Emit(OpCode s.Ret);

return (Operator<T>)me thod.CreateDele gate(typeof(Ope rator<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

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

Similar topics

11
4000
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 looked at the files in the Gyro download but I couldn't find any mention of constraints. Can anyone enlighten me what the current status is and what we can expect when Generics are released? Thanks,
2
2876
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 'System.Collection.Generic.IList'. When performing something like: 'if (typeof(IList<>).IsAssignableFrom(propertyInfo.Type))' where 'propertyInfo' obviously refers to the 'InvoiceLines', the result is always 'false' because indeed 'IList<object>' and...
12
2741
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 it defines the language more completely. Great to use.
1
1647
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
2438
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 "ThrowInConstructor" and "ThrowInFoo". First one throws "MyOwnException" in constructor, second one in "Foo()" method. There is a "GenericCatch" generics class able to accept "ThrowInConstructor" and "ThrowInFoo" as type parameter "<T>". There are two methods in...
4
2818
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 RuleDelegate<T>(T item); In my class my goal is to use a generic list collection to contain my generic delegates. This will allow me to pass this List to another library and call this list of functions. This could provide a new way to build rule base...
7
3257
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 System.Collections.Generic namespace. Literature I have read on this ties generics in with collections, hence articulate their examples as such. That's fine, I understand what is being said. My question is more towards the application and implementation...
4
1450
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 article I start with pointing out the disadvantages of using the classical arrays and .NET collections, and then I show you how generics provide a nice and elegant way of creating flexible and performant strongly typed collections with
6
3067
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 the visual studio designer but the execution is perfect. Without the generic
0
8969
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8792
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9337
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9266
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
1
6754
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
4570
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4826
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3280
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
3
2193
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.