Console.WriteLine()是否需要这么多参数重载?


87

我浏览了文档,发现该Console.WriteLine()方法有一些重载。特别是,我的好奇心和部分困惑与这些有关:

public static void WriteLine(string format, params object[] arg);
public static void WriteLine(string format, object arg0);
public static void WriteLine(string format, object arg0, object arg1);
public static void WriteLine(string format, object arg0, object arg1, object arg2);
public static void WriteLine(string format, object arg0, object arg1, object arg2, object arg3);

似乎多余。在第一个重载之上的其他四个重载有什么需求?第一种方法可以执行其他方法可以执行的所有操作。他们是否试图通过提供额外的重载来解决性能问题,这些重载最多可以处理四个参数(最后一个)?通过最多四个参数组成的数组的开销是否足够大,可以满足这些重载的需要?

Answers:


102

通常,您认为第一个重载就足以满足其他重载的要求。但这并不是严格意义上的,因为params关键字不能用于间接情况,例如方法组绑定。例如

delegate void E(string format, object o1);
E e = Console.WriteLine;

所述params过载不会满足该情况下,它将只工作时,这种特殊的过载是本

public static void WriteLine(string format, object arg0);

不过,这是一个非常神秘的案例。更重要的原因如下

  1. 并非每种CLI语言都需要支持该params关键字。通过消除重载,无需再为简单的WriteLine`调用手动创建数组,从而减轻了这些语言的负担。
  2. 性能。调用params重载会强制调用方分配一个数组,即使它是由编译器隐式完成的。.Net中的分配很便宜,但不是免费的。这样的小事情很快就会加起来,尤其是在像这样的常用方法上Console.WriteLine。其他重载允许常见情况避免这种分配

1
我曾在回答中考虑过方法组的情况,但是我敢肯定,直到C#2.0才引入方法组转换,而WriteLine重载至少要追溯到1.1。
jaket

@jaket方便的语法已在C#2.0中添加。但是,同样一点也适用,如果你使用显式new E(Console.WriteLine)的C#1
CodesInChaos

5
在Console.WriteLine有多慢的情况下,数组分配是否还很明显?
Bryan Boettcher 2014年

3
@insta问题不是速度,而是分配的累积。GC便宜而不是免费,在复杂的应用程序中,GC通常是主要的性能因素。停止不必要分配的常见来源对于性能很重要
JaredPar 2014年

38

重载是为了在不存在params关键字的C ++ / CLI程序中提供便利。


1
这也是一个很好的答案,恕我直言,也是一个很好的问题。
Uwe Keim 2014年

1
啊...这实际上很有道理。真可惜,C ++是我的第一语言。:)
BK 2014年

3
基础知识从第一语言开始,聪明的回答伙伴
dbw

4

我想你们所有人都忘记了C#2.0中引入了params。因此,当params关键字不存在时,.NET 1.1中也存在重载。


jaket提到了这一点。
BK 2014年

阅读他对JaredPar答案的评论。这就是为什么他的答案中没有包含param解释的原因之一。
BK 2014年

@Noobacode,他确实是这么做的,但可以推断(按照我的阅读方式)。我在这里给艾伦一个赞成票(只花一点钱),因为他在更直接的庄园中表示了这一点。
Frank V

1
从此链接, params关键字也存在于.Net 1.1中
Sriram Sakthivel 2014年

1

我认为所提出的问题已经得到了JaredParjaket的很好的解释性回答,但有一点我认为也可能是相关的,

我认为用户可以根据那里的要求使用上述功能的易用性和自由度,因此,当他们真的不需要它时,需要更加方便的方法,而不是强加他们创建数组。

我也想起了过去,当我开始学习C#时, 我几乎不使用数组,而使用数组对我来说是一项复杂的任务,分配它然后使用适当的值对其进行初始化确实非常复杂且耗时...


3
但是的想法params是,您可以传递数组,也可以显式编写所有参数。的方法等void do(params object[])可以与任一称为do(new object[] {"some", "stuff"}do("some", "stuff")。我认为您的观点在这里并不完全适用。
Kroltan

2
@Kroltan,但是您能告诉我有多少初学者确实知道含义吗params,他们知道是否params存在,那么您可以将变量传递为逗号分隔。
2014年

1
@Kroltan我太不知道使用的params可能是这样的很长一段时间,并帮助部分显示在视觉Studion如果我得到array []作为参数,我会考虑提供数组作为参数一样的....
DBW

-3

这样做实际上不是针对性能问题的。但是,增加可用性是其背后的正当理由。

下面的代码将为您提供一点见识。

public class TipCalculator {
    private const double tipRate = 0.18;
    public static int Main(string[] args) {
        double billTotal;
        if (args.Length == 0) {
            Console.WriteLine("usage: TIPCALC total");
            return 1;
        }
        else {
            try {
                billTotal = Double.Parse(args[0]);
            }
            catch(FormatException) {
                Console.WriteLine("usage: TIPCALC total");
                return 1;
            }
            double tip = billTotal * tipRate;
            Console.WriteLine();
            Console.WriteLine("Bill total:\t{0,8:c}", billTotal);
            Console.WriteLine("Tip total/rate:\t{0,8:c} ({1:p1})", tip, tipRate);
            Console.WriteLine(("").PadRight(24, '-'));
            Console.WriteLine("Grand total:\t{0,8:c}", billTotal + tip);
            return 0;
        }
    }
}

请参考链接:http : //msdn.microsoft.com/en-us/library/aa324774 ( v=vs.71) .aspx了解更多信息。


9
如何提高可用性?第一种方法可以执行与其他四种完全相同的操作。您指的是文档,而我只是说我正在浏览文档。我知道该方法用于什么以及如何使用(无论如何我对C#都不陌生)。但是,为什么在第一个之上需要额外的重载。
BK 2014年

我认为他的意思是,仅传递一个参数就没有必要创建一个数组来保存它并将其传递给方法-为什么不仅仅传递一个参数呢?那就是我这样做的原因
KingTravisG 2014年

@ SCassidy1986:如果不是params方法,则不要创建数组,除非您愿意。编译器将自动生成一个。这就是参数和这个问题的重点。
Magus 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.