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);

Это кажется лишним. Зачем нужны четыре других перегрузки поверх первой? Первый метод может делать все, что могут делать другие методы. Есть ли проблема производительности, которую они пытались решить, предоставив дополнительные перегрузки, которые обрабатывают до четырех аргументов (последний из них)? Достаточно ли велики накладные расходы на прохождение массива из четырех аргументов, чтобы обеспечить необходимость в этих перегрузках?

BK
источник

Ответы:

102

В целом вы правы, что первой перегрузки может хватить для других перегрузок. Это не совсем так, потому что paramsключевое слово нельзя использовать для косвенных случаев, таких как привязка группы методов. Например

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

paramsПерегрузка не будет удовлетворять этот случай, он будет работать только тогда , когда эта конкретная перегрузка присутствует

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

Хотя это довольно эзотерический случай. Более важными причинами являются следующие

  1. Не каждый язык интерфейса командной строки требуется для поддержки paramsключевого слова. Наличие перегрузок снижает нагрузку на эти языки, устраняя необходимость вручную создавать массив для простого вызова WriteLine`
  2. Производительность. Вызов paramsперегрузки заставляет вызывающий объект выделить массив, даже если это неявно выполняется компилятором. Размещение в .Net дешево, но не бесплатно. Такие мелочи быстро складываются, особенно в таких часто называемых методах, как Console.WriteLine. Наличие других перегрузок позволяет в общих случаях избежать этого распределения
ДжаредПар
источник
1
В своем ответе я думал о случае группы методов, но я уверен, что преобразование группы методов не было введено до C # 2.0, тогда как перегрузки WriteLine относятся как минимум к 1.1.
jaket 07
@jaket В C # 2.0 был добавлен удобный синтаксис. Но то же самое применимо, если вы используете явное new E(Console.WriteLine)
выражение
5
Заметно ли распределение массива даже с учетом того, насколько медленным является Console.WriteLine?
Брайан Ботчер,
3
@insta проблема не в скорости, а в накоплении распределения. Сборщик мусора - это дешево, но не бесплатно, и в сложных приложениях сборщик мусора часто является доминирующим фактором производительности. Прекращение использования общих источников ненужного выделения памяти важно для производительности
JaredPar
38

Перегрузки предназначены для удобства программ C ++ / CLI, в которых ключевое слово params не существует.

куртка
источник
1
Это отличный ответ, ИМХО, тоже на отличный вопрос.
Уве Кейм
1
Ах ... в этом есть большой смысл. Позор мне, C ++ был моим первым языком. :)
BK
3
основы начинаются с первого языка, умный ответ, приятель
dbw
4

Я думаю, все вы, ребята, забываете, что params был введен в C # 2.0. Следовательно, перегрузки также существуют из .NET 1.1, когда ключевого слова params не было.

Алан
источник
jaket упомянул об этом.
BK
Прочтите его комментарий к ответу ДжаредПара. Это одна из причин, почему он не включил объяснение параметра в свой ответ.
BK
@Noobacode, это правда, но это предположение (как я это читал). Я даю положительный голос (за такую ​​небольшую сумму) Алану, потому что он выразил это более прямо.
Франк V
1
По этой ссылке ключевое слово params существует и в .Net 1.1
Шрирам Сакхивел
1

Я думаю, что на заданный вопрос уже есть хорошие и пояснительные ответы от JaredPar и jaket, но один момент, который, на мой взгляд, тоже может быть актуальным,

Я думаю, что простота использования и свобода для пользователей использовать любую из вышеперечисленных функций в соответствии с их требованиями, там, где это нужно, намного удобнее, чем навязывать их для создания массива, когда они действительно этого не требуют.

Я также думаю о старых временах, когда я начал изучать C #, я почти не использовал массивы, и использование массивов было для меня сложной задачей, назначить его, а затем инициализировать их правильными значениями было действительно сложно и отнимало много времени ...

dbw
источник
3
Но идея в paramsтом, что вы можете либо передать массив, либо явно записать все аргументы. такой метод void do(params object[])можно вызвать с помощью do(new object[] {"some", "stuff"}или do("some", "stuff"). Я не думаю, что ваша точка зрения здесь применима.
Kroltan
2
@Kroltan, но можете ли вы сказать, сколько новичков действительно знают значение, paramsи они знают, есть ли paramsтам, тогда вы можете передавать переменные через запятую.
dbw 08
1
@Kroltan Я тоже paramsдолгое время не знал, что использование может быть таким же, и в разделе справки, отображаемом в Visual 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
Я думаю, что он имеет в виду, что для передачи только одного параметра нет смысла создавать массив для его хранения и передавать его методу - почему бы просто не передать один параметр? Это была бы моя причина сделать что-то подобное
KingTravisG
@ SCassidy1986: Вы не создаете массив, если это метод params, если вы этого не хотите. Компилятор сделает это автоматически. В этом суть обоих параметров и этого вопроса.
Magus