终于看完了Don Box的<
1<essential .net="">>,感触良多,真的是一本好书!
2
3由 C# 的 IDispose 接口而想到
4
5C# 的 using 语句是一种确定性析构的实现,来实现类似 C++ 析构函数的功能,在对象不再需要时进行 清除 工作。但这种语法结构不如 C++ 的析构函数清晰和优美。
6
7using(T obj1=new T(), obj2=new T())
8{
9
10}
11
12这里限制 obj1 和 obj2 必须是同一个类型,而且要求程序员明确给出每个变量的作用范围,实际上, CLR 是可以确定每个对象的作用范围的,在 C# 的垃圾回收技术中,就利用了 CLR 来确定对象的作用范围。
13
14{
15
16Object r1 = new object();
17
18Object r2 = new object();
19
20System.GC.Collect();
21
22r2.ToString();
23
24}
25
26在第三句话进行垃圾回收时 r1 将会被回收掉,尽管从语义的角度讲 r1 仍处在作用范围内。
27
28今天看书,看到 C# 的接口实现,感觉 C# 的语法是否有点过于复杂了。先看下面的一段代码
29
30public interface IVehicle
31
32{
33
34void start(); void stop(); void turn();
35
36}
37
38public class Base : IVehicle
39
40{
41
42void IVehicle .start()
43
44{
45
46Console .WriteLine( "Base.start" );
47
48}
49
50public void stop()
51
52{
53
54Console .WriteLine( "Base.stop" );
55
56}
57
58public virtual void turn()
59
60{
61
62Console .WriteLine( "Base.turn" );
63
64}
65
66}
67
68public class Derive1 : Base
69
70{
71
72// 非法,不能覆盖不存在的方法
73
74//public override void start() { }
75
76// 非法 ,Base.stop 不是虚函数
77
78//public override void stop() { }
79
80// 合法,替代 Base.turn 和 IVehicle.turn
81
82public override void turn()
83
84{
85
86Console .WriteLine( "Derive1.turn" );
87
88}
89
90}
91
92public class Derive2 : Base , IVehicle
93
94{
95
96// 合法,重新实现 IVehicle
97
98void IVehicle .start()
99
100{
101
102Console .WriteLine( "Derive2.start" );
103
104}
105
106// 合法 , 重新实现 IVehicle
107
108public void stop()
109
110{
111
112Console .WriteLine( "Derive2.stop" );
113
114}
115
116// 合法,替换 Ivehicle.turn (但不替换 Base.turn )
117
118public void trun()
119
120{
121
122Console .WriteLine( "Derive2.turn" );
123
124}
125
126}
127
128在 Main 函数中进行如下调用
129
130Derive1 d1 = new Derive1 ();
131
132Console .WriteLine( " 调用 Derive1 的成员 ” );
133
134// d1.start();// 非法调用
135
136d1.turn(); // 调用 Derive1.trun
137
138d1.stop(); // 调用 Base.stop
139
140Console .WriteLine( "Derive1 转换成 Base 后调用成员 ” );
141
142Base b1 = d1;
143
144// b1.start();// 非法调用
145
146b1.turn(); // 调用 Derive1.trun
147
148b1.stop(); // 调用 Base.stop
149
150Console .WriteLine( "Derive1 转换成 IVehicle 后调用成员 " );
151
152IVehicle v1 = d1;
153
154v1.start(); // 调用 Base.start
155
156v1.turn(); // 调用 Derive1.turn
157
158v1.stop(); // 调用 Base.stop
159
160Derive2 d2 = new Derive2 ();
161
162Console .WriteLine( " 调用 Derive2 的成员 " );
163
164//d2.start();// 非法调用
165
166d2.turn(); // 调用 Base.turn
167
168d2.stop(); // 调用 Derive2.stop
169
170Console .WriteLine( "Derive2 转换成 Base 后调用成员 " );
171
172Base b2 = d2;
173
174//b2.start();// 非法调用
175
176b2.turn(); // 调用 Base.turn
177
178b2.stop(); // 调用 Base.stop
179
180Console .WriteLine( "Derive2 转换成 IVehicle 后调用成员 " );
181
182IVehicle v2 = d2;
183
184v2.start(); // 调用 Derive2.start
185
186v2.turn(); // 调用 Base.turn
187
188v2.stop(); // 调用 Derive2.stop
189
190运行结果
191
192调用 Derive1 的成员
193
194Derive1.turn
195
196Base.stop
197
198Derive1 转换成 Base 后调用成员
199
200Derive1.turn
201
202Base.stop
203
204Derive1 转换成 IVehicle 后调用成员
205
206Base.start
207
208Derive1.turn
209
210Base.stop
211
212调用 Derive2 的成员
213
214Base.turn
215
216Derive2.stop
217
218Derive2 转换成 Base 后调用成员
219
220Base.turn
221
222Base.stop
223
224Derive2 转换成 IVehicle 后调用成员
225
226Derive2.start
227
228Base.turn
229
230Derive2.stop
231
232C# 引入了太多复杂的技术,比如在接口的实现和继承方面。这些复杂性带来的好处远远小于他的坏处。程序员理解这些复杂的技术是很困难的,理解不彻底只会带来错误,聪明的程序员也许可以理解并很好的使用这些复杂的技术写出非常优美的代码,但这些代码公布出来后对于想使用这些代码却又不太聪明的程序员就是一种灾难,本来就复杂的技术,再加上聪明的程序员的摆弄就会更加晦涩难懂,一个软件开发队伍不能对要使用的技术和内容有一个一致的理解,软件的错误当然也就在所难免了。
233
234更重要的,这些复杂的技术并非是必须的,同样的问题在没有这些技术时也可以得到解决,方法可能会丑陋一些,但只要解决好了后同样能高效的工作,能容易地被更多人理解,团队开发出的软件却能有更少的错误,更可靠。 Java 就没有这些复杂的东西,这么多年来依然应用的很好。 Java 的失误之处在于过于注重平台移植性,忽略了对使用最为广泛的 Windows 平台应加以宠幸,因此一直不是开发桌面应用首选。
235
236还有一个复杂的地方,虚函数在构造函数中调用, C++ 构造函数中虚函数调用是按非虚函数调用进行的,但 C# 就要按虚函数进行调用,为此,对象的初始化步骤就复杂多了,如果在类成员定义时就对其赋值,该赋值将在基类的构造函数执行前进行,如果在构造函数中对其进行赋值,这样的赋值将在基类的构造函数执行之后进行。
237
238到了代理部分,光弄清对象创建就足以让你的脑袋疼一天。
239
240C# 的函数调用在转变成机器码后,函数调用规则使用 __fastcall 调用规则
241
242软件工程中的大部分 ideas 都是为了控制复杂性
243
244结构化用粗粒度的划分解决复杂性; OO 将状态与行为相联姻,用抽象的方法降低复杂性;组件的方法将程序分成各个部分,部分之间的连接是基于接口和协议,从而降低复杂性。组件编程建立了一个这样的世界,在这个世界里,使用高级语言将各个组件组装起来形成一个完整的应用,这样就可以不需要技术纯熟的程序员也能写出良好的应用。组件编程的前提是问题域可以分成离散的组件,组件之间只需要简单的方法访问就能相互协作。但事实上,软件的某些方面是渗透在整个软件中不能单独分离出来的,比如安全问题、线程管理、并发控制等等。这些问题可以用AOP的方法来解决</essential>