.NET泛型& .NET框架:不够通用? [英] .NET generics & the .NET framework: not generic enough?

查看:104
本文介绍了.NET泛型& .NET框架:不够通用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是对.NET泛型的经验的讨论。

..NET框架(在Visual Studio 2005 Beta 1中实现),

这导致了为什么某些事情是他们的方式的问题

是。


*****摘要&问题*****


简而言之,当前的.NET泛型& .NET框架使得

有时很难甚至不可能编写真正的通用代码。

例如,似乎不可能写出真正的通用

复杂类或真正通用的Matrix类(详见下文)。

因为这似乎是由于两者中的缺点组合而来的。
.NET框架和泛型机制,我有两个问题:


1.为什么重载解析机制在调用函数时只考虑带有泛型参数的重载

用一般的

参数?如果它也考虑了其他重载,那么这将允许我们处理那些没有实现正确的通用

接口的类(参见下面的示例)。 />

2.为什么原始类型的.NET框架类(Byte,Int32,

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

(见下面的例子)?


孤立地说,这些限制都不是一个大问题,因为我们可以很容易地解决它们。然而,他们的组合似乎是因为某些任务不能使用泛型。


*****讨论*****

让我们尝试使用泛型在C#中开发一个通用的Complex类。我们的第一次拍摄的
(非常天真)将如下:


public struct Complex< T>

{

T real;

T imag;


public Complex(T真实,T图像)

{

this.real =真实;

this.imag = imag;

}


public static Complex< T> operator +(

Complex< T> left,Complex< T> right)

{

返回新的Complex< T>(

left.real + right.real,left.imag + right.imag);

}


//其他运营商

}


尝试编译这会产生以下错误:


complex.cs( 24,7):错误CS0019:运算符''''不能应用于'$'
类型为''T''和''''的操作数。

complex。 cs(24,31):错误CS0019:运算符'''''不能应用于'/'
类型为''T''和''''的操作数


这是公平的,因为我们没有为T指定任何约束。

然而,我们应该指定什么约束来使这个工作?

毕竟我们想要使用带有基本类型的Complex类(例如

float,double)*和*用户定义的类型。为了使它可用于

,后者很容易:


public interface IArithmetic< T>

{

T添加(T其他);

//其他操作

}


public struct Complex< T>其中T:IArithmetic< T>

{

T real;

T imag;


public Complex(T真实,T图像)

{

this.real =真实;

this.imag = imag;

}


public static Complex< T> operator +(

Complex< T> left,Complex< T> right)

{

返回新的Complex< T>(

left.real.Add(right.real),

left.imag.Add(right.imag));

}


//其他运营商

}


到目前为止一切顺利,但我们怎么做对于那些没有实现我们的接口的类型,即框架提供的那些,比如

float,double和者decimal?所有这些类型只实现了IComparable,IFormattable,IConvertible和IComparable<这些都没有帮助我们实施复杂。经过一些摆弄
(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



后,我想出了以下内容:


公共接口IArithmetic< T>

{

T添加(T其他);

}


公共结构复杂< T>

{

T real;

T imag;


public Complex(T真实,T图像)

{

this.real =真实;

this.imag = imag;

}


public static Complex< T> operator +(

Complex< T> left,Complex< T> right)

{

返回新的Complex< T>(

添加(left.real,right.real),

添加(left.imag,right.imag));

}


//其他运营商


静态浮动添加(向左浮动,向右浮动)

{

返回左+右;

}


//其他双重超载等


//所有其​​他类型的重载

static U Add< U>(U左,右U)

{

//实施推迟

}

}


我希望两个Add重载允许我在原始的,框架提供的类型和用户提供的类型之间区分



这不起作用,当我添加

两个Complex<时,也会选择泛型重载。浮动>对象。

然后我尝试了各种其他方法来区分类型,但

它们都没有比上面更有趣。看来

当你用泛型类型的参数调用一个函数时

接受所述参数的函数的参数也不可避免地需要

需要是一种通用类型。即第二个添加重载可以带两个

表格:


静态T添加(左边T,右边)





静态U添加< U>(U左,右U)


似乎无论我们选择哪种形式,没有其他Add重载

(例如浮动等等) 。)将被考虑。


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.

推荐答案

Andreas,
Andreas,
1。当我们调用具有通用
参数的函数时,为什么重载解析机制只考虑带泛型参数的重载?


因为方法解析是在编译时完成的,但实际的

泛型参数直到运行时才知道。


2.为什么基本类型的.NET框架类(字节,Int32,十进制,双等)没有实现像IArithmetic那样的接口< T
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
(见下面的例子)?



我不知道为什么。这是一个相当普遍的要求,但我不认为它会是最好的解决方案。这里真正缺少的是运营商

的约束。希望这是他们可以在

框架的未来版本中添加支持。


实现IArithmetic类型的接口作为变通方法

还有其他后果。我看到它的一个主要问题是将值类型转换为已实现的接口需要装箱。

如果你做了一个拳击将会很糟糕

有意义的计算量。


到目前为止一切都那么好,但我们如何才能使这项工作适用于那些没有实现我们的接口,即框架提供的那些,如浮点数,双精度,或者可能是十进制数?


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?




如果你改变了IArithmetic合约,那么它就可以实现了

与其操作类型分开的类型,比如这个


接口IArithmetic< T>

{

T Add(T left,T right);

...

}


您可以为int编写实现和双打等你自己

(原始值类型的集合毕竟是有限的),然后通过工厂获得IArithmetic实现的
。像

public struct Complex< T>其中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

抛出新的TypeLoadException(

T必须是原始的或实现IArithmetic< T>);

}


public static Complex< T> operator +(

Complex< T> left,Complex< T> right)

{

返回新的Complex< T>(

arith.Add(left.real,right.real),

arith.Add(left.imag,right.imag));

}

}


静态类ArithmeticFactory

{

私有类Int32Arithmetic :IArithmetic< int> {

public int Add(int left,int right){return left + right; }

}


public static IArithmethic GetPrimitiveArithmetic< T>()

{

//你可以在这里使用更有效的查找,并使

//实现单例。这只是为了演示

if(typeof(T)== typeof(int))

return(IArithmetic< T>)new Int32Arithmetic();

......等其他原始类型...

}

}

这可以避免拳击开销,但是它当然要输入更多。

由于IArithmetic实现现在是

操作数的外部,它们无法访问私有实例数据可能是也可能不是

是个问题。


Mattias


-

Mattias Sj?gren [MVP] mattias @ mvps.org
http:// www.msjogren.net/dotnet/ | http://www.dotnetinterop.com

请回复到新闻组。



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.


嗨Mattias,
Hi Mattias,
1.为什么重载解析机制当我们用一般的
参数调用一个函数时,只考虑带泛型参数的重载?
因为方法解析是在编译时完成的,但实际的通用参数不是直到运行时才知道。
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.




我想这取决于你所谓的编译时和运行时。在.NET中,你实际上有两个编译时间:首先,泛型类(C#,VB等)

被编译成MSIL。稍后(在运行时),MSIL被编译为本机

代码。据我所知,在某些情况下,在第二个编译阶段之前,可能会推迟涉及通用

参数的函数调用的重载解析。

>



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.为什么基本类型的.NET框架类(字节,Int32,十进制,双等)没有实现像IArithmetic这样的接口; T
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.




确实,操作员限制将是最好的解决方案。 />
实现IArithmetic类型的接口作为变通方法会产生其他后果。我看到的一个主要问题是,将值类型转换为已实现的界面需要装箱。
如果你进行了大量的计算,所有拳击对于性能都会很糟糕。


除非我弄错了泛型中接口的全部意义,否则你不需要支付那个拳击费用。界面只有

确保您的类型符合某些要求。然后通用代码

直接处理它实例化的类型的对象,并且从来没有必须包装任何东西。

到目前为止好的,但是我们怎么做才能使这个类型不能实现我们的接口,即框架提供的那些,如
float,double和者decimal?



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?


<如果您更改了IArithmetic合同,以便可以通过与其操作类型分开的类型来实现它,就像这样接口IArithmetic< T>
{
T Add(T left,T right);
...


你可以编写int和double等实现自己
(原始值类型集合毕竟是有限的),然后通过工厂获得IArithmetic实现。类似



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>
这可以避免拳击开销,但它当然会更多打字。
自从IArithmetic实现现在是
操作数的外部,他们无法访问可能会或可能不会成为问题的私有实例数据。


<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.




好吧,我忘了提到为什么我要将泛型用于假设的

复杂/矩阵库。其中一个主要原因是要实现至少与C ++相当的性能。\\ b
。我相信如果我们对Complex / Matrix元素上的每个操作进行
运行时调度,这是不可能的。


问候,


安德烈亚斯



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


马蒂亚斯,
如果你做了一个拳击,那么拳击会很糟糕/>有意义的计算量。


我在使用IComparable< T>时找到了对于值类型(System.Int32 for

示例),没有装箱,为什么IArithmetic< T>导致拳击

继续下去?


正如安德烈亚斯所说,这不是IComparable的全部重点< T>

接口?避免拳击!


我同意真正的操作符约束可能是最好的,不完全

确定它们如何工作因为Int32上的+是IL操作码,+上

System.Decimal是一个重载运算符,运算符约束

需要一个重载运算符,要求Int32提供过载

运算符,虽然对于Int32的+已经是IL操作码?


我不明白为什么IArithmetic< T>今天不能轻易实现...(我是

确定有原因;-)


我没有想过使用像Factory这样的方法那:我的想法,如果我需要

IArithmetic< T>是为类型内置类型创建代理类,类似于System.Data.SqlTypes类型的
,我的类将具有IArithmetic< T>

约束,但是你将它传递给ArithmeticInt32而不是Int32。


接口IArithmetic< T>

{

T Add(T other) ;

...

}


struct ArithmeticInt32:IArithmetic< Int32>

{

Int32值;


Int32添加(Int32其他)

{

返回值+其他;

}


...


//隐含转换可能

}


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


public struct Complex< T> :其中T:算术< T>

{

}


复杂< ArithmeticInt32> ci;

复杂< ArithmeticDouble> cd;


当然复杂< T>可能实现IArithmetic< T>也是为了

本身......


我唯一关心的是IArithmetic< T>是否应该有一个单独的接口

所有数学运算符,或者应该有单独的接口,例如

IAdd< T>,ISubtract< T>, IMul​​tiply< T>,IDivide< T>等等

IArithmetic< T>继承自?我可以看到创建泛型类

需要支持添加但是(TimeSpan)但是乘法不会使

感觉......


只是一个想法

Jay


" Mattias Sj?gren" <毫安******************** @ mvps.org>在消息中写道

news:%2 **************** @ TK2MSFTNGP10.phx.gbl ... Andreas,
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。当我们使用泛型
参数调用函数时,为什么重载解析机制只考虑带泛型参数的重载?
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。为什么原始类型的.NET框架类(字节,Int32,十进制,双等)没有实现类似IArithmetic的接口< T
2. Why do .NET framework classes for primitive types (Byte, Int32,
Decimal, Double, etc.) not implement an interface like IArithmetic< T
(见下面的例子)?



我不知道为什么。这是一个相当普遍的要求,但我认为它不是最好的解决方案。这里真正缺少的是运营商
约束。希望他们可以在框架的未来版本中添加支持。

实现IArithmetic类型的接口作为变通方法会产生其他后果。我看到的一个主要问题是,将值类型转换为已实现的界面需要装箱。
如果你进行了大量的计算,所有拳击对于性能都会很糟糕。



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?



如果你改变了IArithmetic合约,以便可以通过与其操作类型分开的类型来实现它,喜欢这个

接口IArithmetic< T>
{添加(T左,右);
...
}

你可以编写int和double的实现,比如你自己
(原始值类型的集合毕竟是有限的),然后通过工厂获得IArithmetic实现。像

public struct Complex< T>其中T:new()
{T real;
T imag;
静态算术< T> arith;

static Complex(){
if(typeof(T).IsPrimitive)
arith = ArithmeticFactory.GetPrimitiveArithmetic< T>();
if if( typeof(IArithmetic< T>)。IsAssignableFrom(typeof(T)))
arith = new T()as IArithmetic< T> ;;

抛出新的TypeLoadException(
" ; T必须是原始的或实现IArithmetic< T>");
}
公共静态复杂< T> operator +(
Complex< T> left,Complex< T> right)
{
返回new Complex< T>(
arith.Add(left.real,right.real),
arith.Add(left.imag,right.imag));
}
}

静态类ArithmeticFactory
私有类Int32Arithmetic:IArithmetic< int> {
public int Add(int left,int right){return left + right; }

公共静态IArithmethic GetPrimitiveArithmetic< T>()
//
//你可以在这里使用更有效的查找,并制作
//实现单身人士这只是为了演示
if(typeof(T)== typeof(int))
return(IArithmetic< T>)new Int32Arithmetic();
...等等原始类型......
}

这可以避免拳击开销,但它当然会输入更多内容。
自从IArithmetic实现以来现在是
操作数的外部,他们无法访问可能会或可能不会成为问题的私人实例数据。

Mattias
-
Mattias Sj?gren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
请仅回复新闻组。



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.



这篇关于.NET泛型&amp; .NET框架:不够通用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆