《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)。如果找到则将操作符编译为对操作符重载方法的调用,否则编译错误。