.NET 2.0 SUCK中的泛型 [英] Generics in .NET 2.0 SUCK

查看:72
本文介绍了.NET 2.0 SUCK中的泛型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于严厉的语言感到抱歉,但我必须向某人发泄我的愤怒

实际上理解我在说什么。抱怨我的女朋友

除了使我们的

关系紧张之外不会产生任何有意义的结果...


我只是下载Visual C#Express Edition搞乱.NET 2.0泛型。

作为一个数字倾向的开发人员,我想写的第一件事是
是一个通用的复数类。我还有一些非常大的矢量和

矩阵库,我很乐意转换为使用泛型。


想象一下,当我发现我是什么时,我感到惊讶想要的基本上是不可能的。我想要一个复杂的数字类,它可以处理任何基本数据

类型如下:complex< float> ;, complex< double>,complex< decimal>等等。

这是在C ++中经常使用的东西,以及那里的泛型的主要

应用程序之一。


这是我的第一次尝试(这只是一个摘录):


struct complex< T>

{

public T re,im;

complex< T>(T re,T im)

{

this.re = re; this.im = im;

}

complex< T>总和(复数< T> a,复数< T> b)

{

返回新的复数< T>(a.re + b.re,a.im + b.im);

}

}


这样的东西可以在C ++中使用,因为它没有约束

类型参数。但是在.NET中,当你指定一个没有

约束的类型参数时,它被认为是一个System.Object,当然这不是
有一个+运算符。 br />

所以我想,可能有办法为T

指定一个方法约束,这样T必须有一定的(静态)方法或某个算子

方法。但唯一这样的是new()约束指定

一个类必须有一个默认的构造函数。


我的第二个想法是,有可能像IArithmetic这样的界面。

这当然很复杂,因为接口不能包含

静态方法。但是像


接口IArithmetic< T> {

void Add(T a);

void Subtract(T a);

void Multiply(T a);

void除以(T a);

}


应该可以解决问题。这不是很优雅,但已经足够了。

鉴于有一个名为IComparable< T>的接口。这不应该是太多问了。也许应该有一些更细微的东西,比如


界面IAddable< T> {

无效添加(T a);

}


....


接口

算术< T>:IAddable< T>,ISubtractable< T>,IMultipiable< T>,IDivisible< T>

{

}


或者别的什么。此解决方案类似于使用

IComparable和IComparable< T>所采用的方法。


但系统名称空间中不存在此类接口。所以我必须将所有基本数据类型包装到实际实现这个

接口的结构中,如下所示:


struct ArithmeticInt:IArithmetic< int> {

私有int值;

...

}


struct ArithmeticDouble:IArithmetic<双> {

私人双倍价值;

...

}


但这将是一个很多工作,甚至更糟糕的是,会导致绝对的b / b
性能,因为根据我的经验,.NET JIT编译器太笨了,无法获得包装代码。


当然有一些解决方法,例如为操作设置单独的类型参数

,如下所示:


struct Complex< T,Ops>其中Ops:IArithmeticOps< T>

{

...

}


但是这个产生不可接受的性能。


真正需要的是一种指定* method * * constraints *而不是

的接口约束和new()约束的方法。


另一种选择是允许接口中的静态方法,并在System命名空间中提供一个IArithmethic接口,但我更喜欢

第一个选项。


如果没有这样的东西,泛型只适用于打印的集合。

添加如此多的新语法和复杂性只是为了使收藏更快

和更多类型安全似乎浪费时间!

Sorry about the harsh language, but I have to vent my anger to somebody who
actually understands what I am talking about. Complaining to my girlfriend
is not going to produce any meaningful results other than straining our
relationship...

I just downloaded Visual C# Express Edition to mess with .NET 2.0 generics.
Being a numerically inclined developer, the first thing I wanted to write
was a generic complex number class. I also have some quite large vector and
matrix libraries that I would love to convert to use generics.

Imagine my surprise when I found out that what I want is basically
impossible. I want a complex number class that can work with any basic data
type like so: complex<float>, complex<double>, complex<decimal> and so on.
This is something that is done very often in C++ and one of the main
applications of generics there.

This was my first try (this is only an excerpt):

struct complex<T>
{
public T re,im;
complex<T>(T re,T im)
{
this.re=re;this.im=im;
}
complex<T> Sum(complex<T> a,complex<T> b)
{
return new complex<T>(a.re+b.re,a.im+b.im);
}
}

Something like this would work in C++, since it does not have constraints on
type parameters. But in .NET, when you specify a type parameter without
constraints it is assumed to be a System.Object, which of course does not
have a + operator.

So I thought, probably there is a way to specify a method constraint for T
such that T must have a certain (static) method or a certain operator
method. But the only thing like this is the new() constraint to specify
that a class must have a default constructor.

My second thought was that there might be some interface like IArithmetic.
This is of course complicated by the fact that interfaces can not contain
static methods. But something like

interface IArithmetic<T> {
void Add(T a);
void Subtract(T a);
void Multiply(T a);
void Divide(T a);
}

should do the trick. This would not be very elegant, but quite sufficient.
Given that there is an interface called IComparable<T> this should not be
too much to ask. Maybe there should even be something more granular like

interface IAddable<T> {
void Add(T a);
}

....

interface
IArithmetic<T>:IAddable<T>,ISubtractable<T>,IMulti pliable<T>,IDivisible<T>
{
}

or something. This solution would be similar to the approach taken with
IComparable and IComparable<T>.

But no such interface exists in the System namespace. So I would have to
wrap all the basic data types into structs that actually implement this
interface, like so:

struct ArithmeticInt : IArithmetic<int> {
private int value;
...
}

struct ArithmeticDouble : IArithmetic<double> {
private double value;
...
}

But this would be a lot of work and, even worse, would lead to absymal
performance since in my experience the .NET JIT compiler is too dumb to get
rid of the wrapper code.

There are of course some workarounds like having a separate type parameter
for the operations, like this:

struct Complex<T,Ops> where Ops:IArithmeticOps<T>
{
...
}

But this yields inacceptable performance.

What is really required is a way to specify *method* *constraints* instead
of just interface constraints and the new() constraint.

Another option would be to allow static methods in interfaces and to provide
an IArithmethic interface in the System namespace, but I would prefer the
first option.

Without something like this, generics are only good for typed collections.
Adding so much new syntax and complexity just to make collections faster
and more type safe seems like a waste of time!

推荐答案

只是为了支持我的断言.NET JIT无法删除

包装器代码,这是一个小基准。 YMMV,但在我的机器上,第二个

循环总是需要大约第一个循环的两倍。所以使用包装器

类不是性能关键代码的选项。


---------------- -------------------------------------------------- ----

#region使用指令


使用System;

使用System.Collections.Generic;

使用System.Text;


#endregion


命名空间ConsoleApplication1

{

interface IAddable< T>

{

void Add(T a);

}

struct AddableInt:IAddable< int>

{

int value;

public void Add(int a)

{

值+ = a;

}

}

班级计划

{

static void Main(string [] args)

{

//这是JIT

测试();

//这个是真实的

测试();

Console.ReadLine();

}

static void Test(){

int x0 = 0;

AddableInt x 1 = new AddableInt();

DateTime time0 = DateTime.Now;

for(int i = 0;我< 10亿; i ++)

{

x0 + = i;

}

TimeSpan delta0 = DateTime.Now - time0;

DateTime time1 = DateTime.Now;

for(int i = 0; i< 1000000000; i ++)

{

x1.Add(i);

}

TimeSpan delta1 = DateTime.Now - time1;

Console.WriteLine(delta0 );

Console.WriteLine(delta1);

}

}

}

Just to back up my assertion that the .NET JIT is not capable of removing
wrapper code, here is a small benchmark. YMMV, but on my machine the second
loop always takes about twice as long as the first loop. So using wrapper
classes is not an option for performance-critical code.

----------------------------------------------------------------------
#region Using directives

using System;
using System.Collections.Generic;
using System.Text;

#endregion

namespace ConsoleApplication1
{
interface IAddable<T>
{
void Add(T a);
}
struct AddableInt : IAddable<int>
{
int value;
public void Add(int a)
{
value += a;
}
}
class Program
{
static void Main(string[] args)
{
//This is for the JIT
Test();
//This one is for real
Test();
Console.ReadLine();
}
static void Test() {
int x0 = 0;
AddableInt x1 = new AddableInt();
DateTime time0 = DateTime.Now;
for (int i = 0; i < 1000000000; i++)
{
x0 += i;
}
TimeSpan delta0 = DateTime.Now - time0;
DateTime time1 = DateTime.Now;
for (int i = 0; i < 1000000000; i++)
{
x1.Add(i);
}
TimeSpan delta1 = DateTime.Now - time1;
Console.WriteLine(delta0);
Console.WriteLine(delta1);
}
}
}


" Ruediger Klaehn" < KL **** @ gamemakers.de>写道:


[... rant删除...]
"Ruediger Klaehn" <kl****@gamemakers.de> wrote:

[...rant deleted...]
如果没有这样的东西,泛型只适用于打字的集合。<添加如此多的新语法和复杂性只是为了使集合更快
更安全类型似乎浪费时间!
Without something like this, generics are only good for typed collections.
Adding so much new syntax and complexity just to make collections faster
and more type safe seems like a waste of time!




好​​吧,我认为制作集合类型安全和更快是值得所有新的

语法和共谋。

哦,我的女朋友也许会同意我的意见,她很乐意有

更多类型安全! :)


Sam

-

但是没有限制条件很难,是的!而且我得到了naggin的感觉,我在某个地方读到了它应该知道的约束。记忆是一种奇怪的野兽。



Ah well, I think making collections typesafe and faster is worth all the new
syntax and complicity.
Oh, and my girlfriend would probably agree with me, too, she''d love to have
more typesafety! :)

Sam
--
But no constraints is tough, yes! And I got the naggin feeling I read
somewhere it should know constraints. Memory is a strange beast.


2004年7月27日星期二14:47:18 +0200,Ruediger Klaehn

< kl ** **@gamemakers.de>写道:


< snip>
On Tue, 27 Jul 2004 14:47:18 +0200, Ruediger Klaehn
<kl****@gamemakers.de> wrote:

<snip>

当我发现我想要的东西基本上是不可能的时候,想象一下我的惊喜。我想要一个复杂的数字类,它可以处理任何类似的基本数据类型:complex< float>,complex< double>,complex< decimal>
这是C ++中常用的东西,也是泛型的主要应用之一。
< snip>


是的,遗憾的是不可能。我认为这个2.0的变化不会有机会,但是你应该把这个讨论带到

beta新闻组并尝试影响未来的发展方向,因为我知道这个主题正在考虑之中:
http://communities.microsoft.com/new...idbey&slcid=us

没有这样的东西,泛型只适用于打印的集合。
添加如此多的新语法和复杂性只是为了使集合更快
更多类型安全似乎浪费时间!

Imagine my surprise when I found out that what I want is basically
impossible. I want a complex number class that can work with any basic data
type like so: complex<float>, complex<double>, complex<decimal> and so on.
This is something that is done very often in C++ and one of the main
applications of generics there. <snip>

Yes, it is unfortunately impossible. I don''t think there is a chance
of this changing for 2.0, but you should take this discussion to the
beta newsgroups and try to influence the future direction, because I
know this very subject is being given some thought:
http://communities.microsoft.com/new...idbey&slcid=us

Without something like this, generics are only good for typed collections.
Adding so much new syntax and complexity just to make collections faster
and more type safe seems like a waste of time!



这是主观的,但我不得不反对。在我使用的许多应用程序中,收藏品很普遍,而且泛型将会使它们不仅类型安全且性能高,而且还可以制作代码

更优雅。


-

Scott
http://www.OdeToCode.com


这篇关于.NET 2.0 SUCK中的泛型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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