银河

SKYIV STUDIO

  博客园 :: 首页 :: 博问 :: 闪存 :: :: :: 订阅 订阅 :: 管理 ::

我们知道,C# 语言的构造函数的名称和类名相同。

静态构造函数最多只能有一个。不能有返回值,不能有参数,不能有访问修饰符。

实例构造函数可以有多个。不能有返回值,可以有参数,可以有访问修饰符。

如果没有为对象提供实例构造函数,则 C# 编译器将创建一个默认的实例构造函数,该构造函数实例化对象,并将所有成员变量设置为默认值。

1 using System;
2 using System.Diagnostics;
3
4  namespace Skyiv.Bin
5 {
6 public class Foo
7 {
8 static Foo()
9 {
10 Console.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name);
11 }
12
13 public Foo()
14 {
15 Console.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name);
16 }
17
18 protected void Bar()
19 {
20 Console.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name);
21 }
22
23 private static void Main()
24 {
25 Console.WriteLine(new StackTrace().GetFrame(0).GetMethod().Name);
26 new Foo().Bar();
27 }
28 }
29 }

上述 C# 程序的运行结果是:

C> Foo
.cctor
Main
.ctor
Bar

上述 C# 程序运行时首先调用静态构造函数(.cctor),接着调用 Main 静态方法,然后调用实例构造函数(.ctor),最后调用 Bar 实例方法。

也就是说,静态构造函数名称是 .cctor (我猜想这是 class constructor 的缩写),实例构造函数的名称是 .ctor (我猜想这是 constructor 的缩写)。这可以从下图的 IL 代码看出:

 

既然 C# 语言的构造函数的名称和类名相同,那么在 C# 语言中就无法再定义和类名相同名称的方法了。

那么下面的 Test.cs 是否合法呢?

1 namespace Skyiv.Bin
2 {
3 static class Test
4 {
5 static void Main()
6 {
7 Bar.Bar();
8 }
9 }
10 }

 

让我们看看下述的 Bar.cs 吧:

1 using System;
2
3  namespace Skyiv.Bin
4 {
5 public static class Bar
6 {
7 public static void Bar1()
8 {
9 }
10 }
11 }

首先使用 csc /t:library Bar.cs 命令将 Bar.cs 编译为 Bar.dll。

接着使用 ildasm /out:Bar.il Bar.dll 命令将 Bar.dll 反汇编为 Bar.il:

1
2  // Microsoft (R) .NET Framework IL Disassembler. Version 3.5.30729.1
3  
4
5
6
7  // Metadata version: v2.0.50727
8  .assembly extern mscorlib
9 {
10 .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
11   .ver 2:0:0:0
12 }
13  .assembly Bar
14 {
15 .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
16 .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
17   63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
18   .hash algorithm 0x00008004
19 .ver 0:0:0:0
20 }
21  .module Bar.dll
22  // MVID: {01B600EE-97DD-472C-AB80-D5087E640A51}
23  .imagebase 0x00400000
24  .file alignment 0x00000200
25 .stackreserve 0x00100000
26  .subsystem 0x0003 // WINDOWS_CUI
27  .corflags 0x00000001 // ILONLY
28 // Image base: 0x007E0000
29  
30
31  // =============== CLASS MEMBERS DECLARATION ===================
32  
33  .class public abstract auto ansi sealed beforefieldinit Skyiv.Bin.Bar
34 extends [mscorlib]System.Object
35 {
36 .method public hidebysig static void Bar1() cil managed
37 {
38 // 代码大小 2 (0x2)
39   .maxstack 8
40 IL_0000: nop
41 IL_0001: ret
42 } // end of method Bar::Bar1
43  
44 } // end of class Skyiv.Bin.Bar
45  
46
47  // =============================================================
48  
49  // *********** 反汇编完成 ***********************
50 // 警告: 创建了 Win32 资源文件 Bar.res

将上述 Bar.il 文件第 36 行的 Bar1 改名为 Bar 。

 

然后再使用 ilasm /dll Bar.il 命令重新将 Bar.il 汇编为 Bar.dll。

最后,就可以使用 csc /r:Bar.dll Test.cs 来编译了。

 

可见,虽然 C# 语言不允许有和类名相同名称的(不是构造函数的)方法,但是 MSIL 是允许的,而且也能够在 C# 语言中调用该方法。

我建议修改 C# 语言规范,将静态构造函数的名称改为 .cctor,实例构造函数的名称改为 .ctor。

这样,不但可以和 MSIL 语言保持一致,而且有以下好处:

  • 在 C# 程序中允许定义和类名相同名称的(不是构造函数的)方法。
  • 对 C# 程序进行重构时,如果需要改变类名,就不用相应修改构造函数的名称了。
  • 如果想拷贝一个类的代码来创建一个新类,也不用修改新类的构造函数的名称了。

不知各位朋友的看法如何?

posted on 2010-02-27 12:17  银河  阅读(3591)  评论(24编辑  收藏  举报