Archive for June, 2009

Peter Coad的7项修炼

Saturday, June 27th, 2009

作者:王海鹏 摘自《程序员》2009年第2期


petercoad7e9a1b9e4bfaee782bc

Peter Coad是我喜欢的一位面向对象专家和软件创业者。他在上世纪九十年代与人合著了6本关于面向对象软件的分析、设计和编程的书籍。他以《面向对象分析》一书中和Yourdon共创的Coad/Yourdon方法而成名。1999年,他创建了TogetherSoft公司。2003年,TogetherSoft卖给了Borland公司,他成为了Borland公司的副总裁。后来,他离开了Borland,兴趣转向了软件之外,教人读希腊文版的圣经。
  
他最值得一提的技术贡献,就是提出了“彩色UML”建模的方法,这也是他最后一本书《彩色UML建模》的主题。在这种建模方法中,他使用了4种颜色,代表4种不同设计意图的类,创造性地回答了面向对象分析和设计的一个根本问题:“怎样识别类,并确定方法和属性?”这本书已由机械工业出版社引入版权并出了中文版,很荣幸,我是这本中文版的译者。
  
我对Coad的关注始于十多年前,那时朋友向我推荐了北大出版社引进的《面向对象分析》一书。后来因为学习Java、UML建模、关注Borland公司的产品,又看到了TogetherSoft和Coad的名字。再后来,敏捷方法学兴起,我又看到了Coad,他是特征驱动开发(FDD)的主要支持者。向师傅学习,要学师傅练功的方法,而不只是师傅的招式。我想知道的是:为什么Peter Coad会发明彩色UML的方法?或者说,Peter Coad是怎样炼成的?
  
在他1994年左右的一篇文章中,为这个问题给出了一些提示。这篇文章标题是“Amplified Learning”,介绍了“7种智能”的理论和应用。
  
语言是第一种智能。著名的通天塔的故事体现了自然语言表达的重要性:失去了语言沟通能力,团队协作就成为了不可能的任务。语言能力的习得,有一句话可以概括:“听说领先,读写跟上”。学习本国语言和外语都是如此。语言的重要性,实际上体现的是沟通的重要性。据说,当年TogetherSoft公司在面试时,会先让被面试的人选一个与软件开发无关的话题讲15分钟。通过这样的面试环节,可以了解面试者对生活的一些理解和表达沟通的能力。这里我还想强调一下中国程序员的英语能力。由于软件方面的最好的信息几乎都是英语的,所以良好的英语能力对程序员有很大的帮助。一般来说,最成功的人都是拥有最好信息的人。

代码的可读性也是语言能力的体现。Knuth在1984年提出的Literate Programming,把编程比喻为写文学作品。既然是文学作品,就会有不同的风格。有晦涩难懂,也有深入浅出、生动有趣。所以作为一名好的程序员,需要对自然语言和编程语言都有深刻的理解,要懂得欣赏和创造文章之美,代码之美。

那么什么样的文章是好文章?一个留美回来的英语作文教师曾对我说,好文章首先要有“something new(新东西)”。新的观点、新的解释、新的视角、新的实践、新的证据……都可以。然后才是布局谋篇、遣词造句。这是西方鼓励创新的思路,所以我们会看到软件业的创新层出不穷。中国人对好文章的评判标准更注重传统。《文心雕龙》里提出的标准是“本乎道,师乎圣,体乎经,酌乎纬,变乎骚”。把软件提升到道的高度,那就是Bjarne Stroustrup所说的,“人类文明运行于软件之上”。
  
数理逻辑是第二种智能。我们需要对数字敏感,需要具有归纳和演绎的能力。这样的能力虽然也包含在语言学习之中,但更多地包含在数学、物理等理科科目中。在西方,学理科的学生几乎都读过波利亚的《怎样解题》一书。数学是思维的体操,它让我们的思维更灵活、更缜密。懂得欣赏数学之美的人,会看到简洁的公式和逻辑的力量。许多大学的计算机系都是从数学系分出来的,一些老师以前是学数学或物理的。史书记载:“尧造围棋,教子丹朱”。学围棋也是对逻辑思维很好的锻炼。和数学一样,从围棋中我们也可以看到,从一些简单的规则出发,可以怎样建造一个瑰丽的宫殿群。
  
以上两种智能是学校教育的核心,体现在语、数、外三门主课上。能够熟练灵活地运用语言进行沟通,并能够运用逻辑推理来找出问题和解决问题,学校的基础教育就是成功的。但除此之外,还有一些扩展性的智能,对于我们软件开发者也很重要。
  
空间色彩是第三种智能。九十年代是GUI的十年,在这十年里,软件的美由内而外,扩展到了视觉领域。叔本华说,“美是最高级的善,创造美是最高级的乐趣”。但是,我们不时会看到一些殊无美感的设计,那真是叫“乏善可陈”。Apple公司的操作系统中,利用色彩来表示窗口的控制按钮,给人以艺术的享受。Peter Coad的彩色UML建模方法利用4种色彩来表示4种不同的架构型,通过色彩强化了信息沟通的效果。我还记得当初在Borland公司的集成环境中第一次看到彩色语法制导时,带来的那种震撼。作为程序员,我们经常需要阅读图表、画设计草图、运用图表或幻灯片来传达信息,空间色彩能力也是相当重要的。

“流光容易把人抛。红了樱桃,绿了芭蕉。”“知否?知否?应是绿肥红瘦。”中国人讲究“诗中有画,画中有诗”。软件是散文,是诗,其中也蕴含着色彩和空间之美。
  
音乐是第四种智能。科学家有音乐特长的例子比比皆是,并且他们都认为,音乐对他们的专业是有启发的。Spring框架的作者之一Rod Johnson拥有音乐博士学位。旋律和节奏是音乐训练的两个主要方面。从小学乐器的人,长大了唱歌不容易走音。我喜欢在工作环境中使用背景音乐,这样能舒缓压力,激发创造力。《庄子•养生主》载,“庖丁为文惠君解牛,手之所触,肩之所倚,足之所履,膝之所踦,砉然响然,奏刀騞然,莫不中音,合于桑林之舞,乃中经首之会。”庖丁是个解牛的专家,是个哲学家,也是个音乐家。
  
运动锻炼是第五种智能。许多职业棋手都通过运动锻炼,保持有活力的工作和思考,使自己处于最佳状态。极限编程(XP)在一开始提出“每周工作四十小时”作为一种最佳实践,但是如果你的身体有问题,就会连四十小时都做不到。后来XP将这一实践改成了“保持有活力的工作”,我想大概是因为有些身体好的人,每周工作六十小时也一样很有效率吧。要养成锻炼的习惯,“每天锻炼一小时,健康工作五十年,幸福生活一辈子”。
  
以上三种智能,体现在音、体、美这三门副课上。
  
自知是第六种智能。曾子曰:吾日三省吾身。苏格拉底说:“认识你自己”。蘧伯玉年五十而知四十九年非。正确地认识和评价自己,不断地反省自己,这才是进步的基础。《从优秀到卓越》一书的作者柯林斯说,你应该问自己一个问题:在哪个领域你可以做到世界前三?人贵有自知之明。
  
知人是第七种智能。越来越多的工作,正由团队承担。有一本书名叫“Teamwork Is an Individual Skill(团队合作是一项个人技能)”。要成为团队的一员,你需要读懂他人,并具备一定的社交技能。然后,通过实现团队的目标来实现自我。“己欲立而立人,己欲达而达人。”如果你是团队的领导,那么知人善任就是一项重要的能力。刘邦因为用对了张良、韩信、萧何而得天下。

寻找怎样的人作为合作的伙伴或朋友?益者三友:友直、友谅、友多闻。怎样看人不走眼?子曰:视其所以,观其所由,察其所安;人焉廋哉。人焉廋哉。

以铜为镜,可以正衣冠;以古为镜,可以知兴替;以人为镜,可以明得失。所以知人也可以促进自知。
  
知人者智,自知者明。以上两种智能,就属于情商的范畴了。
我们每个人在这7种智能上的发展都不尽相同,如何在这些方面提高自己,是否也是值得考虑的一个问题呢?

《Flash Builder 4 快速入门》正式发布

Thursday, June 25th, 2009


目录

第一章 Flash Builder 4 背景

1.1 从Flex Builder到Flash Builder

第二章 Flash Builder 4 界面

2.1 主界面 
2.2 主菜单
2.3 工具条 
2.4 主要窗口

·第三章 Flash Builder 4 新特性

3.1 Package explorer 
3.2 悬停时的ASDOC提示 
3.3 Getter & Setter 
3.4 自动生成EventHandler 
3.5 条件断点

第四章 Flex SDK 4 新特性

4.1 主题 
4.2 布局 
4.3 特效 
4.4 样式 
4.5 状态 
4.6 双向绑定 
4.7 ASDoc 
4.8 SWFObject 与 HTML Template

第五章 自定义组件开发

5.1 自定义Flex组件 
5.2 MXML组件开发 
5.3 ActionScript组件开发

第六章 与服务端通信

6.1 通过Http Service与服务端通信 
6.2 通过Web Service与服务端通信 
6.3 通过Remoting与服务端通信 
6.4 与Flash Media Server交互

《Flash Builder 4 快速入门》内容简介

        在Adobe发布Flash Builder 4后,艾睿论坛 (bbs.airia.cn)编辑团队协作完成了这部教学。 《Flash Builder 4  快速入门》6月25日正式发布第一个版本,今后还会根据读者需要进行更新。


本书适合谁读?

        《Flash Builder 4  快速入门》除了适合想学习FLEX开发和正在学习FLEX开发的朋友,也广泛适用与FLASH、Actionscript开发者进行转型和深入学习。包括.NET、JAVA开发人员在内,这本书都将为你日后的含RIA开发工作奠定牢固的知识基础。


章节简介:

        本书1-2章主要为新接触FLEX开发的朋友提供入门帮助,以图文并茂的方式从零基础开始指引新手走进FLEX开发,如果是有一定基础的FLEX开发者,这两章可以简单翻阅。3-5章开始进阶学习, 介绍FB4 / FLEX SDK 4 新特性与开发实例,适合绝大多数的FLEX开发者阅读。 第6章为通信服务方面的必备知识,这一章以实际案例的方式展示了FLEX与服务端通信的4种方式。 

本书作者:

       本书凝聚了艾睿编辑团队各位作者的大量心血,以下是参与本书编辑的作者,如果你在阅读的期间遇到问题也可以进入Flash Builder快速入门专栏联系作者,或进入作者的博客与其交流。

他们分别是(排名不分先后): 

罗楷
http://www.flextheworld.com 
kevin.luo.sl@gmail.com 

郭峰 
http://www.hydra1983.com 
Edison@airia.cn 

郑会宾 
http://www.flexers.cn 
momoko8443@163.com 

唐凡 
http://www.tangfanzone.com 
woodytf@sina.com 

陆仕桑 
http://lushisang.com 
lushisang@gmail.com 

Flash Builder 4快速入门艾睿专栏:

http://www.airia.cn/flashbuilder/

QQ邮箱的自动转发功能

Friday, June 19th, 2009

在 QQ 邮箱中设置将 xxx@qq.com 中收到的邮件自动转发到 yyy@gmail.com 中。

测试一:用 yyy@gmail.com 向 xxx@qq.com 发送邮件 zzz。
期待结果:邮箱 yyy@gmail.com 应该收到邮件 zzz。
实际结果:等了半天都没有收到 zzz。

怎么回事?难道自动转发无效吗?

测试二:用邮箱 www@163.com 向 xxx@qq.com 发送邮件 zzz。
期待结果:yyy@gmail.com 收到邮件 zzz。
实际结果:几秒后 yyy@gmail.com 收到了邮件 zzz。

可见,QQ 邮箱无法将来自某个邮箱的邮件再自动转发回该邮箱。
使用 Gmail 及网易邮箱代替 xxx@qq.com 重复测试一时,结果无误。

[转载]也谈回国发展-责任和义务

Saturday, June 13th, 2009

本文转载自Kevin的QQ空间,原文请看这里


 在各个论坛看了很久了,感触很多。那么多的朋友一谈到回国发展,就是对比两边的收入,生活质量呀,等等,少有人谈到自己对家庭,对社会的责任和义务,也很少有人谈及自己的理想。

其实,回国发展真正的重点是发展,回国如同出国只是一个手段而已,而发展的目标是成功,那么你就就应该明白,这不仅仅是个如何回国的问题,而是一个如何成功的问题。

国内这些年发展很快,加上原有的基础非常落后,各个行业都在发生变革,机会非常地多。但是,中国也有很多人,非常聪明也非常勤快,他们都在各自的岗位上努力着,任何一个人如果想成功,都要有相当的积累和付出的。但是,做为一个海龟,你的知识、经历等本身就是一种积累,应该说,你离成功比别人近一点,但是不代表你一定成功。各位海龟的留学经历和国外工作的经历,你只能当成学业有成,(事实上,国外的工作经历才是最成功的学习),真正要成功一定要学以致用。因此,回国前要先有一个良好的心理准备。

这里我想谈点有关责任和义务的问题。中国的教育有一个非常龌龊的地方,就是排名,多次的排名之后,让中国教育培养出来的人心态非常畸形,就是什么都喜欢排名,排名的最后结果就是人非常地自私,没有责任心。如果一个人要谈发展,一定要明白,成功的首要因素是有责任感。在这个世界上,没有任何一个人可以完全凭借自己的能力去做所有的事情,要成功,必须和一批人一起去奋斗。但是,我接触的相当一部分海龟,根本没有意识到,那如何谈成功呢?去年,我接待了一个在美国已经生活很多年的朋友,他在美国的发展不错,积累了一点家底,自己感觉也很良好,现在回国想找一些机会投资,但是接触了几天,我就知道他一定不会成功。他个人虽然很聪明,也基本适应了美国社会,拿到了比较高的薪水,也有了一定的财富积累,但是我可以保证他不会成功。因为,他对他父母的赡养就是简单地理解为给钱,他为他的父母买了一套比较好的房子,他认为就尽到责任了。中国上一代人是非常容易满足的,但是你尽到责任了么,难道老人辛苦养育你仅仅为了得到一套房子么?得到一些钱财么?一个对父母都不能够尽到责任的人,你还奢望什么人能够真心帮助你,真心和你一起去奋斗呢,那你还从哪里谈成功呢?

在这里的人,很多人都拥有比常人多的知识,比常人高的智商,简单一句话,拥有更容易成功的资本。但是一定要明白一个道理,一个成功的人首先是个有责任心的人。

另外一个事情就是理想和成功的定义。

市场经济刚刚真正开始冲击中国人,很多人都以赚多少钱为目标,也简单地做为评判成功的标准。冷静下来想一想,真正一个人一个人能够一生中能够消耗多少金钱呢?现在国内的很多小有成就的人基本上开始意识到大家已经过了温饱阶段,一些比较有头脑的,现在已经重新开始思考成功的定义了。我这里讲讲我的一点经历,可能对大家有点启发。

去年过完年,我拜访了我的几个代理商,其中一个代理商,老板是31-32岁,国内一个地区师范院校毕业的。毕业后没有找到工作,于是来到广州,在电脑城找了份工作,慢慢地自己租下铺面开始了他的创业,经过7、8年的打拼,终于积攒了点家底。由于没有什么背景,也没有什么过硬的技术和关系,就是靠着勤奋练就的狡猾和精明在商场上血拼。当然,他也有自知之明,他把他挣的钱都提现成个人资产,从来不做扩大再生产。年初,我拜访他的时候,又是以原来的那种利益为导向的方式和他谈今年的合作,告诉他如果做我们公司的产品,会多赚多少钱,但是他很严肃地告诉我他现在在读EMBA,这个阶段他不会轻易地调整他公司的经营策略,请我放心。谈了一会,他突然告诉我,他现在的目标不是赚钱,他现在只考虑他和公司未来的发展方向,‘我出身贫寒,我个人现在的投资资产每年产生的效益已经让我根本无法花完。我现在要考虑的事情是如何帮助我的员工成功,在我们这个小集体都成功之后,我要考虑的是如何做一些对社会有意义有贡献的事情。’ 这是他的原话,我非常吃惊,确切地说是震惊,真的,这个老板原来可是把486CPU的表面打磨后喷上586的标签就拿出去卖的无良商贩。

还有一次,我听电台里的采访。采访的是一位30多岁的女士,她应该是天分及家庭背景很好的人,大学毕业没有多久,就出国读书,学业有成后回国工作,然后又觉得学的东西不是不是很适合中国的发展,又重新选择专业出国读书,学成后回国创业发展。当主持人问她出国最大的感受时,她回答说,出国这么多年,总是感觉老外瞧不起我们中国人,思前想后,她认为中国落后的根源是教育。当主持人问她的理想时,她沉默了一会,她说我把真实的想法说出来,请听众和主持人不要笑我。后来在主持人的追问下,她说她不一定有能力去改变什么,但是她想尽力去做点事情,她希望她在60岁退休的时候,能够捐出一个亿发展祖国的教育事业。

每个人的背景不同,但是应该明白,成功更多是评判标准是你为了这个社会做了多少,你的做的对这个社会有多少价值。大陆很穷,因此,第一批富起来的人巧取豪夺,不择手段,但是慢慢地,社会分配制度向合理的方向转变了,一批受过良好教育有社会责任感的人富了,成功的定义和整个社会的价值观也发生了变化。因此,如果你成功的定位或者说你的理想和别人就有差距,那么也就不要谈成功了。

当然,脚踏实地,先把自己的日子过好,先让自己的家人幸福,尽到自己该尽的责任,然后再谈发展。中国很大,机会特别地多,但是不管任何人,首先要有目标有理想,才能谈成功。

来源:文 学 城

泛型类的嵌套类型必须定义泛型类型参数?

Sunday, June 7th, 2009

使用 Reflector 将 List <T>类反编译,得到如下结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Collections;
using System.Collections.ObjectModel;
using System.Runtime.InteropServices;
 
namespace dnAnalysisTest
{
    [Serializable, DebuggerTypeProxy(typeof(Mscorlib_CollectionDebugView<>)), DebuggerDisplay("Count = {Count}")]
    public class List<t> : IList</t><t>, ICollection</t><t>, IEnumerable</t><t>, IList, ICollection, IEnumerable
    {
        // Fields
        private const int _defaultCapacity = 4;
        private static T[] _emptyArray;
        private T[] _items;
        private int _size;
        [NonSerialized]
        private object _syncRoot;
        private int _version;
 
        // Methods
        static List()
        {
            List</t><t>._emptyArray = new T[0];
        }
 
        public List()
        {
            this._items = List</t><t>._emptyArray;
        }
 
        public List(IEnumerable</t><t> collection)
        {
            if (collection == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
            }
            ICollection</t><t> is2 = collection as ICollection</t><t>;
            if (is2 != null)
            {
                int count = is2.Count;
                this._items = new T[count];
                is2.CopyTo(this._items, 0);
                this._size = count;
            }
            else
            {
                this._size = 0;
                this._items = new T[4];
                using (IEnumerator</t><t> enumerator = collection.GetEnumerator())
                {
                    while (enumerator.MoveNext())
                    {
                        this.Add(enumerator.Current);
                    }
                }
            }
        }
 
        public List(int capacity)
        {
            if (capacity < 0)
            {
                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity, ExceptionResource.ArgumentOutOfRange_SmallCapacity);
            }
            this._items = new T[capacity];
        }
 
        public void Add(T item)
        {
            if (this._size == this._items.Length)
            {
                this.EnsureCapacity(this._size + 1);
            }
            this._items[this._size++] = item;
            this._version++;
        }
 
        public void AddRange(IEnumerable<t> collection)
        {
            this.InsertRange(this._size, collection);
        }
 
        public ReadOnlyCollection</t><t> AsReadOnly()
        {
            return new ReadOnlyCollection</t><t>(this);
        }
 
        public int BinarySearch(T item)
        {
            return this.BinarySearch(0, this.Count, item, null);
        }
 
        public int BinarySearch(T item, IComparer</t><t> comparer)
        {
            return this.BinarySearch(0, this.Count, item, comparer);
        }
 
        public int BinarySearch(int index, int count, T item, IComparer</t><t> comparer)
        {
            if ((index < 0) || (count < 0))
            {
                ThrowHelper.ThrowArgumentOutOfRangeException((index < 0) ? ExceptionArgument.index : ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
            }
            if ((this._size - index) < count)
            {
                ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
            }
            return Array.BinarySearch<t>(this._items, index, count, item, comparer);
        }
 
        public void Clear()
        {
            Array.Clear(this._items, 0, this._size);
            this._size = 0;
            this._version++;
        }
 
        public bool Contains(T item)
        {
            if (item == null)
            {
                for (int j = 0; j < this._size; j++)
                {
                    if (this._items[j] == null)
                    {
                        return true;
                    }
                }
                return false;
            }
            EqualityComparer<t> comparer = EqualityComparer</t><t>.Default;
            for (int i = 0; i < this._size; i++)
            {
                if (comparer.Equals(this._items[i], item))
                {
                    return true;
                }
            }
            return false;
        }
 
        public List<toutput> ConvertAll<toutput>(Converter<t , TOutput> converter)
        {
            if (converter == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.converter);
            }
            List<toutput> list = new List</toutput><toutput>(this._size);
            for (int i = 0; i < this._size; i++)
            {
                list._items[i] = converter(this._items[i]);
            }
            list._size = this._size;
            return list;
        }
 
        public void CopyTo(T[] array)
        {
            this.CopyTo(array, 0);
        }
 
        public void CopyTo(T[] array, int arrayIndex)
        {
            Array.Copy(this._items, 0, array, arrayIndex, this._size);
        }
 
        public void CopyTo(int index, T[] array, int arrayIndex, int count)
        {
            if ((this._size - index) < count)
            {
                ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
            }
            Array.Copy(this._items, index, array, arrayIndex, count);
        }
 
        private void EnsureCapacity(int min)
        {
            if (this._items.Length < min)
            {
                int num = (this._items.Length == 0) ? 4 : (this._items.Length * 2);
                if (num < min)
                {
                    num = min;
                }
                this.Capacity = num;
            }
        }
 
        public bool Exists(Predicate<t> match)
        {
            return (this.FindIndex(match) != -1);
        }
 
        public T Find(Predicate<t> match)
        {
            if (match == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
            }
            for (int i = 0; i < this._size; i++)
            {
                if (match(this._items[i]))
                {
                    return this._items[i];
                }
            }
            return default(T);
        }
 
        public List<t> FindAll(Predicate</t><t> match)
        {
            if (match == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
            }
            List</t><t> list = new List</t><t>();
            for (int i = 0; i < this._size; i++)
            {
                if (match(this._items[i]))
                {
                    list.Add(this._items[i]);
                }
            }
            return list;
        }
 
        public int FindIndex(Predicate<t> match)
        {
            return this.FindIndex(0, this._size, match);
        }
 
        public int FindIndex(int startIndex, Predicate</t><t> match)
        {
            return this.FindIndex(startIndex, this._size - startIndex, match);
        }
 
        public int FindIndex(int startIndex, int count, Predicate</t><t> match)
        {
            if (startIndex > this._size)
            {
                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
            }
            if ((count < 0) || (startIndex > (this._size - count)))
            {
                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count);
            }
            if (match == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
            }
            int num = startIndex + count;
            for (int i = startIndex; i < num; i++)
            {
                if (match(this._items[i]))
                {
                    return i;
                }
            }
            return -1;
        }
 
        public T FindLast(Predicate<t> match)
        {
            if (match == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
            }
            for (int i = this._size - 1; i >= 0; i--)
            {
                if (match(this._items[i]))
                {
                    return this._items[i];
                }
            }
            return default(T);
        }
 
        public int FindLastIndex(Predicate</t><t> match)
        {
            return this.FindLastIndex(this._size - 1, this._size, match);
        }
 
        public int FindLastIndex(int startIndex, Predicate</t><t> match)
        {
            return this.FindLastIndex(startIndex, startIndex + 1, match);
        }
 
        public int FindLastIndex(int startIndex, int count, Predicate</t><t> match)
        {
            if (match == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
            }
            if (this._size == 0)
            {
                if (startIndex != -1)
                {
                    ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
                }
            }
            else if (startIndex >= this._size)
            {
                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
            }
            if ((count < 0) || (((startIndex - count) + 1) < 0))
            {
                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count);
            }
            int num = startIndex - count;
            for (int i = startIndex; i > num; i--)
            {
                if (match(this._items[i]))
                {
                    return i;
                }
            }
            return -1;
        }
 
        public void ForEach(Action</t><t> action)
        {
            if (action == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
            }
            for (int i = 0; i < this._size; i++)
            {
                action(this._items[i]);
            }
        }
 
        public Enumerator<t> GetEnumerator()
        {
            return new Enumerator</t><t>((List</t><t>)this);
        }
 
        public List</t><t> GetRange(int index, int count)
        {
            if ((index < 0) || (count < 0))
            {
                ThrowHelper.ThrowArgumentOutOfRangeException((index < 0) ? ExceptionArgument.index : ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
            }
            if ((this._size - index) < count)
            {
                ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
            }
            List<t> list = new List</t><t>(count);
            Array.Copy(this._items, index, list._items, 0, count);
            list._size = count;
            return list;
        }
 
        public int IndexOf(T item)
        {
            return Array.IndexOf</t><t>(this._items, item, 0, this._size);
        }
 
        public int IndexOf(T item, int index)
        {
            if (index > this._size)
            {
                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index);
            }
            return Array.IndexOf</t><t>(this._items, item, index, this._size - index);
        }
 
        public int IndexOf(T item, int index, int count)
        {
            if (index > this._size)
            {
                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index);
            }
            if ((count < 0) || (index > (this._size - count)))
            {
                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count);
            }
            return Array.IndexOf</t><t>(this._items, item, index, count);
        }
 
        public void Insert(int index, T item)
        {
            if (index > this._size)
            {
                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_ListInsert);
            }
            if (this._size == this._items.Length)
            {
                this.EnsureCapacity(this._size + 1);
            }
            if (index < this._size)
            {
                Array.Copy(this._items, index, this._items, index + 1, this._size - index);
            }
            this._items[index] = item;
            this._size++;
            this._version++;
        }
 
        public void InsertRange(int index, IEnumerable<t> collection)
        {
            if (collection == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
            }
            if (index > this._size)
            {
                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index);
            }
            ICollection</t><t> is2 = collection as ICollection</t><t>;
            if (is2 != null)
            {
                int count = is2.Count;
                if (count > 0)
                {
                    this.EnsureCapacity(this._size + count);
                    if (index < this._size)
                    {
                        Array.Copy(this._items, index, this._items, index + count, this._size - index);
                    }
                    if (this == is2)
                    {
                        Array.Copy(this._items, 0, this._items, index, index);
                        Array.Copy(this._items, (int)(index + count), this._items, (int)(index * 2), (int)(this._size - index));
                    }
                    else
                    {
                        T[] array = new T[count];
                        is2.CopyTo(array, 0);
                        array.CopyTo(this._items, index);
                    }
                    this._size += count;
                }
            }
            else
            {
                using (IEnumerator<t> enumerator = collection.GetEnumerator())
                {
                    while (enumerator.MoveNext())
                    {
                        this.Insert(index++, enumerator.Current);
                    }
                }
            }
            this._version++;
        }
 
        private static bool IsCompatibleObject(object value)
        {
            if (!(value is T) && ((value != null) || typeof(T).IsValueType))
            {
                return false;
            }
            return true;
        }
 
        public int LastIndexOf(T item)
        {
            return this.LastIndexOf(item, this._size - 1, this._size);
        }
 
        public int LastIndexOf(T item, int index)
        {
            if (index >= this._size)
            {
                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index);
            }
            return this.LastIndexOf(item, index, index + 1);
        }
 
        public int LastIndexOf(T item, int index, int count)
        {
            if (this._size == 0)
            {
                return -1;
            }
            if ((index < 0) || (count < 0))
            {
                ThrowHelper.ThrowArgumentOutOfRangeException((index < 0) ? ExceptionArgument.index : ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
            }
            if ((index >= this._size) || (count > (index + 1)))
            {
                ThrowHelper.ThrowArgumentOutOfRangeException((index >= this._size) ? ExceptionArgument.index : ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_BiggerThanCollection);
            }
            return Array.LastIndexOf</t><t>(this._items, item, index, count);
        }
 
        public bool Remove(T item)
        {
            int index = this.IndexOf(item);
            if (index >= 0)
            {
                this.RemoveAt(index);
                return true;
            }
            return false;
        }
 
        public int RemoveAll(Predicate</t><t> match)
        {
            if (match == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
            }
            int index = 0;
            while ((index < this._size) && !match(this._items[index]))
            {
                index++;
            }
            if (index >= this._size)
            {
                return 0;
            }
            int num2 = index + 1;
            while (num2 < this._size)
            {
                while ((num2 < this._size) && match(this._items[num2]))
                {
                    num2++;
                }
                if (num2 < this._size)
                {
                    this._items[index++] = this._items[num2++];
                }
            }
            Array.Clear(this._items, index, this._size - index);
            int num3 = this._size - index;
            this._size = index;
            this._version++;
            return num3;
        }
 
        public void RemoveAt(int index)
        {
            if (index >= this._size)
            {
                ThrowHelper.ThrowArgumentOutOfRangeException();
            }
            this._size--;
            if (index < this._size)
            {
                Array.Copy(this._items, index + 1, this._items, index, this._size - index);
            }
            this._items[this._size] = default(T);
            this._version++;
        }
 
        public void RemoveRange(int index, int count)
        {
            if ((index < 0) || (count < 0))
            {
                ThrowHelper.ThrowArgumentOutOfRangeException((index < 0) ? ExceptionArgument.index : ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
            }
            if ((this._size - index) < count)
            {
                ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
            }
            if (count > 0)
            {
                this._size -= count;
                if (index < this._size)
                {
                    Array.Copy(this._items, index + count, this._items, index, this._size - index);
                }
                Array.Clear(this._items, this._size, count);
                this._version++;
            }
        }
 
        public void Reverse()
        {
            this.Reverse(0, this.Count);
        }
 
        public void Reverse(int index, int count)
        {
            if ((index < 0) || (count < 0))
            {
                ThrowHelper.ThrowArgumentOutOfRangeException((index < 0) ? ExceptionArgument.index : ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
            }
            if ((this._size - index) < count)
            {
                ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
            }
            Array.Reverse(this._items, index, count);
            this._version++;
        }
 
        public void Sort()
        {
            this.Sort(0, this.Count, null);
        }
 
        public void Sort(IComparer<t> comparer)
        {
            this.Sort(0, this.Count, comparer);
        }
 
        public void Sort(Comparison</t><t> comparison)
        {
            if (comparison == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
            }
            if (this._size > 0)
            {
                IComparer</t><t> comparer = new Array.FunctorComparer</t><t>(comparison);
                Array.Sort</t><t>(this._items, 0, this._size, comparer);
            }
        }
 
        public void Sort(int index, int count, IComparer</t><t> comparer)
        {
            if ((index < 0) || (count < 0))
            {
                ThrowHelper.ThrowArgumentOutOfRangeException((index < 0) ? ExceptionArgument.index : ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
            }
            if ((this._size - index) < count)
            {
                ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
            }
            Array.Sort<t>(this._items, index, count, comparer);
            this._version++;
        }
 
        IEnumerator</t><t> IEnumerable</t><t>.GetEnumerator()
        {
            return new Enumerator</t><t>((List</t><t>)this);
        }
 
        void ICollection.CopyTo(Array array, int arrayIndex)
        {
            if ((array != null) && (array.Rank != 1))
            {
                ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
            }
            try
            {
                Array.Copy(this._items, 0, array, arrayIndex, this._size);
            }
            catch (ArrayTypeMismatchException)
            {
                ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
            }
        }
 
        IEnumerator IEnumerable.GetEnumerator()
        {
            return new Enumerator</t><t>((List</t><t>)this);
        }
 
        int IList.Add(object item)
        {
            List</t><t>.VerifyValueType(item);
            this.Add((T)item);
            return (this.Count - 1);
        }
 
        bool IList.Contains(object item)
        {
            return (List</t><t>.IsCompatibleObject(item) && this.Contains((T)item));
        }
 
        int IList.IndexOf(object item)
        {
            if (List</t><t>.IsCompatibleObject(item))
            {
                return this.IndexOf((T)item);
            }
            return -1;
        }
 
        void IList.Insert(int index, object item)
        {
            List</t><t>.VerifyValueType(item);
            this.Insert(index, (T)item);
        }
 
        void IList.Remove(object item)
        {
            if (List</t><t>.IsCompatibleObject(item))
            {
                this.Remove((T)item);
            }
        }
 
        public T[] ToArray()
        {
            T[] destinationArray = new T[this._size];
            Array.Copy(this._items, 0, destinationArray, 0, this._size);
            return destinationArray;
        }
 
        public void TrimExcess()
        {
            int num = (int)(this._items.Length * 0.9);
            if (this._size < num)
            {
                this.Capacity = this._size;
            }
        }
 
        public bool TrueForAll(Predicate<t> match)
        {
            if (match == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
            }
            for (int i = 0; i < this._size; i++)
            {
                if (!match(this._items[i]))
                {
                    return false;
                }
            }
            return true;
        }
 
        private static void VerifyValueType(object value)
        {
            if (!List<t>.IsCompatibleObject(value))
            {
                ThrowHelper.ThrowWrongValueTypeArgumentException(value, typeof(T));
            }
        }
 
        // Properties
        public int Capacity
        {
            get
            {
                return this._items.Length;
            }
            set
            {
                if (value != this._items.Length)
                {
                    if (value < this._size)
                    {
                        ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value, ExceptionResource.ArgumentOutOfRange_SmallCapacity);
                    }
                    if (value > 0)
                    {
                        T[] destinationArray = new T[value];
                        if (this._size > 0)
                        {
                            Array.Copy(this._items, 0, destinationArray, 0, this._size);
                        }
                        this._items = destinationArray;
                    }
                    else
                    {
                        this._items = List</t><t>._emptyArray;
                    }
                }
            }
        }
 
        public int Count
        {
            get
            {
                return this._size;
            }
        }
 
        public T this[int index]
        {
            get
            {
                if (index >= this._size)
                {
                    ThrowHelper.ThrowArgumentOutOfRangeException();
                }
                return this._items[index];
            }
            set
            {
                if (index >= this._size)
                {
                    ThrowHelper.ThrowArgumentOutOfRangeException();
                }
                this._items[index] = value;
                this._version++;
            }
        }
 
        bool ICollection</t><t>.IsReadOnly
        {
            get
            {
                return false;
            }
        }
 
        bool ICollection.IsSynchronized
        {
            get
            {
                return false;
            }
        }
 
        object ICollection.SyncRoot
        {
            get
            {
                if (this._syncRoot == null)
                {
                    Interlocked.CompareExchange(ref this._syncRoot, new object(), null);
                }
                return this._syncRoot;
            }
        }
 
        bool IList.IsFixedSize
        {
            get
            {
                return false;
            }
        }
 
        bool IList.IsReadOnly
        {
            get
            {
                return false;
            }
        }
 
        object IList.this[int index]
        {
            get
            {
                return this[index];
            }
            set
            {
                List</t><t>.VerifyValueType(value);
                this[index] = (T)value;
            }
        }
 
        // Nested Types
        [Serializable, StructLayout(LayoutKind.Sequential)]
        public struct Enumerator : IEnumerator</t><t>, IDisposable, IEnumerator
        {
            private List</t><t> list;
            private int index;
            private int version;
            private T current;
            internal Enumerator(List</t><t> list)
            {
                this.list = list;
                this.index = 0;
                this.version = list._version;
                this.current = default(T);
            }
 
            public void Dispose()
            {
            }
 
            public bool MoveNext()
            {
                if (this.version != this.list._version)
                {
                    ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
                }
                if (this.index < this.list._size)
                {
                    this.current = this.list._items[this.index];
                    this.index++;
                    return true;
                }
                this.index = this.list._size + 1;
                this.current = default(T);
                return false;
            }
 
            public T Current
            {
                get
                {
                    return this.current;
                }
            }
            object IEnumerator.Current
            {
                get
                {
                    if ((this.index == 0) || (this.index == (this.list._size + 1)))
                    {
                        ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);
                    }
                    return this.Current;
                }
            }
            void IEnumerator.Reset()
            {
                if (this.version != this.list._version)
                {
                    ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
                }
                this.index = 0;
                this.current = default(T);
            }
        }
    }
}

新建一个项目,将该类加入进行编译,不知道为什么,编译时总是会报错。
The non-generic type ‘dnAnalysisTest.List<T>.Enumerator’ cannot be used with type arguments 
不晓得微软的同志是怎么编译通过的~~