关于“.WriteLine()是否需要这么多重载”的笔记

在Stack Overflow上看到一个较热门的问题,作笔记于此。
Console.WriteLine()有以下如此多的重载:
1 public static void WriteLine(string format, params object[] arg);
2 public static void WriteLine(string format, object arg0);
3 public static void WriteLine(string format, object arg0, object arg1);
4 public static void WriteLine(string format, object arg0, object arg1, object arg2);
5 public static void WriteLine(string format, object arg0, object arg1, object arg2, object arg3);
第一个重载能够替代后面的所有重载,为什么还需要后面的重载呢?
JaredPar给出了相关解答:
1.  params参数无法在间接方法绑定中自由的使用,如以下代码:
delegate void E(string format, object o1);
E e = Console.WriteLine;

如在之后按params重载的思路,使用e("{0}, {1}", "a", "b")将无法编译通过。对于指定参数的委托,如需要使用到WriteLine,非params的重载是应该存在的;

2.  并非所有的CLI都支持params的语法;

3.  从性能的角度来说,每次调用public static void WriteLine(string format, params object[] arg),都将分配托管堆空间用于存储对象,哪怕是如下代码:

     

static void Main(string[] args)
{
       DemoFunc("a", "b", "c");
       DemoFunc("a", "b", "c");
}

public static void DemoFunc(params string[] val)
{
}
.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // 代码大小       78 (0x4e)
  .maxstack  3
  .locals init ([0] string[] CS$0$0000)
  IL_0000:  nop
  IL_0001:  ldc.i4.3
  IL_0002:  newarr     [mscorlib]System.String
  IL_0007:  stloc.0
  IL_0008:  ldloc.0
  IL_0009:  ldc.i4.0
  IL_000a:  ldstr      "a"
  IL_000f:  stelem.ref
  IL_0010:  ldloc.0
  IL_0011:  ldc.i4.1
  IL_0012:  ldstr      "b"
  IL_0017:  stelem.ref
  IL_0018:  ldloc.0
  IL_0019:  ldc.i4.2
  IL_001a:  ldstr      "c"
  IL_001f:  stelem.ref
  IL_0020:  ldloc.0
  IL_0021:  call       void ConsoleApplicationDemo2.Program::DemoFunc(string[])
  IL_0026:  nop
  IL_0027:  ldc.i4.3
  IL_0028:  newarr     [mscorlib]System.String
  IL_002d:  stloc.0
  IL_002e:  ldloc.0
  IL_002f:  ldc.i4.0
  IL_0030:  ldstr      "a"
  IL_0035:  stelem.ref
  IL_0036:  ldloc.0
  IL_0037:  ldc.i4.1
  IL_0038:  ldstr      "b"
  IL_003d:  stelem.ref
  IL_003e:  ldloc.0
  IL_003f:  ldc.i4.2
  IL_0040:  ldstr      "c"
  IL_0045:  stelem.ref
  IL_0046:  ldloc.0
  IL_0047:  call       void ConsoleApplicationDemo2.Program::DemoFunc(string[])
  IL_004c:  nop
  IL_004d:  ret
} // end of method Program::Main
从IL中可以看出,.NET都会重复分配托管堆空间。在此,由于程序较为简单,对于GC的压力较小,但当程序趋于复杂时,过多的分配托管堆空间对GC的压力是很大的,而GC往往会成为复杂程序效率的瓶颈。
原文地址:https://www.cnblogs.com/tonychan/p/3597737.html