《CLR via C#》读书笔记(6) -- 操作符重载

其实操作符重载没怎么用过,之前还觉得是个很神秘的东西。CLR本身是没有操作符这一说的,操作符经过编译器编译后会生成对某个方法的调用。(某些基元类型除外,比如两个int型相加,编译器会直接生成add指令。)

而我们对操作符的重载,则会被编译器编译成类型的一个方法。

举例说明:

public class Man
{
        public string Name { get; set; }

        public int Age { get; set; }
}

public class Women
{
        public string Name { get; set; }

        public int Age { get; set; }

        public static Family operator +(Women women, Man man) 
//C#要求操作符的重载必须为public static方法。此处第一个参数表示操作符的左元参数,第二个参数表示操作符的右元参数 {
return new Family() { Man = man, Women = women }; } }

我们可以看一下编译器生成的IL代码:

编译器为重载的+操作符生成了一个op_Addition的方法。

再看看调用代码:

class Program
{
        static void Main(string[] args)
        {
            Man man = new Man() { Name = "Jensen", Age = 26 };
            Women women = new Women() { Name = "Secret", Age = 27 };
            Family family = women + man;
        }
}

生成的IL代码:

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       87 (0x57)
  .maxstack  2
  .locals init ([0] class [Operator]Operator.Man man,
           [1] class [Operator]Operator.Women women,
           [2] class [Operator]Operator.Family 'family',
           [3] int32 a,
           [4] int32 b,
           [5] int32 c,
           [6] class [Operator]Operator.Man '<>g__initLocal0',
           [7] class [Operator]Operator.Women '<>g__initLocal1')
  IL_0000:  nop
  IL_0001:  newobj     instance void [Operator]Operator.Man::.ctor()
  IL_0006:  stloc.s    '<>g__initLocal0'
  IL_0008:  ldloc.s    '<>g__initLocal0'
  IL_000a:  ldstr      "Jensen"
  IL_000f:  callvirt   instance void [Operator]Operator.Man::set_Name(string)
  IL_0014:  nop
  IL_0015:  ldloc.s    '<>g__initLocal0'
  IL_0017:  ldc.i4.s   26
  IL_0019:  callvirt   instance void [Operator]Operator.Man::set_Age(int32)
  IL_001e:  nop
  IL_001f:  ldloc.s    '<>g__initLocal0'
  IL_0021:  stloc.0
  IL_0022:  newobj     instance void [Operator]Operator.Women::.ctor()
  IL_0027:  stloc.s    '<>g__initLocal1'
  IL_0029:  ldloc.s    '<>g__initLocal1'
  IL_002b:  ldstr      "Secret"
  IL_0030:  callvirt   instance void [Operator]Operator.Women::set_Name(string)
  IL_0035:  nop
  IL_0036:  ldloc.s    '<>g__initLocal1'
  IL_0038:  ldc.i4.s   27
  IL_003a:  callvirt   instance void [Operator]Operator.Women::set_Age(int32)
  IL_003f:  nop
  IL_0040:  ldloc.s    '<>g__initLocal1'
  IL_0042:  stloc.1
  IL_0043:  ldloc.1
  IL_0044:  ldloc.0
  IL_0045:  call       class [Operator]Operator.Family [Operator]Operator.Women::op_Addition(class [Operator]Operator.Women,
                                                                                             class [Operator]Operator.Man) 
//此处是+操作符所对应的IL代码:对类型Women的op_Addition方法的调用。
  IL_004a:  stloc.2
  IL_004b:  ldc.i4.1
  IL_004c:  stloc.3
  IL_004d:  ldc.i4.2
  IL_004e:  stloc.s    b
  IL_0050:  ldloc.3
  IL_0051:  ldloc.s    b
  IL_0053:  add
  IL_0054:  stloc.s    c
  IL_0056:  ret
} // end of method Program::Main

对操作符的支持其实是编译器为我们提供的便捷功能。在编译代码的时候,编译器如果发现操作符(比如+),它会去查找操作的类型是否定义了操作符重载方法(比如op_Addition)。如果找到则将操作符编译为对操作符重载方法的调用,否则编译错误。

posted @ 2012-12-04 15:55  self.refactoring  阅读(327)  评论(0编辑  收藏  举报