Подтвердить что ты не робот

С#: ключевое слово params vs. list

Каковы преимущества/недостатки использования ключевого слова params vs. List в качестве входных данных для некоторой функции С#?

В основном, что такое производительность и другие компромиссы.

4b9b3361

Ответ 1

Ключевое слово params - синтаксический сахар, обработанный компилятором С#. под капотом, он фактически поворачивает

void Foo(params object[] a) { ... }
Foo(1,2,"THREE");

в

void Foo(object[] a) { ... }
Foo(new object[] { 1, 2, "THREE" })

С точки зрения производительности, о которой вы спрашиваете, вызов params выполняется быстрее, потому что немного быстрее создать массив, чем создавать List < > . Не существует разницы в производительности между этими двумя фрагментами выше.

Ответ 2

Лично я использую params при записи функций, которые принимают несколько входов, предоставляемых другим программистом (например, String.Format), и IEnumerable при записи функций, которые берут список элементов данных, предоставляемых компьютером (для пример File.Write).

Показатели производительности незначительны. Беспокойство о выполнении тривиальной вещи, как это, это то, о чем говорил Дональд Кнут в знаменитой цитате "преждевременной оптимизации - это корень всех злых".

Тем не менее, кажется, что его зацепило, поэтому здесь вы идете:

Результаты для 10 миллионов итераций:

params took 308 ms
list took 879 ms

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

Код для тестирования (скомпилирован и запущен в режиме выпуска с использованием VS2008)

class Program
{
    const int COUNT = 10000000;

    static IEnumerable<string> m_value = null;

    static void ParamsMethod(params string[] args)
    { m_value = args; } // do something with it to stop the compiler just optimizing this method away

    static void ListMethod(List<string> args)
    { m_value = args; } // do SOMETHING with it to stop the compiler just optimizing this method away

    static void Main(string[] args)
    {
        var s = new Stopwatch();
        s.Start();
        for (int i = 0; i < COUNT; ++i)
            ParamsMethod("a", "b", "c");

        Console.WriteLine("params took {0} ms", s.ElapsedMilliseconds);

        s.Reset();
        s.Start();
        for (int i = 0; i < COUNT; ++i)
            ListMethod(new List<string> { "a", "b", "c" });

        Console.WriteLine("list took {0} ms", s.ElapsedMilliseconds);
    }
}

Ответ 3

Ключевое слово params позволяет динамически передавать переменное количество аргументов функции, не беспокоясь о таких ошибках компилятора:

public string PrefixFormatString(string p, string s, params object[] par)
{ 
    return p + string.Format(s, par);
}
...
PrefixFormatString("COM", "Output Error #{0} - Error = {1}", errNum, errStr);

Если вы передаете список, вам нужно создать список, прежде чем вы сможете его передать:

public string PrefixFormatString(string p, string s, List<object> par)
{ 
    return p + string.Format(s, par.ToArray());
}
...
List<object> l = new List<object>(new object[] { errNum, errStr });
PrefixFormatString("COM", "Output Error #{0} - Error = {1}", l);

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

Обратите внимание, что это очень похоже на передачу простой переменной массива. Единственное различие заключается в том, что компилятор установит параметры в массив для вас... Я не уверен на 100%, но я думаю, что техническое различие - это просто синтаксический сахар - в любом случае вы действительно передаете массив любых введите этот параметр.

Ответ 4

Ну, params позволяет использовать более красивый синтаксис при его вызове, но список (при условии, что вы имеете в виду IList<>) более гибкий, поскольку различные классы могут реализовать интерфейс. Передача List<> имеет смысл только в том случае, если вам нужно выполнить определенные операции в списке, которые не поддерживаются интерфейсом (например, ToArray()).

Ответ 5

Ну, с ключевым словом params вы можете ввести аргументы в метод, подобный этому:

MethodName(1, 2, 3, 4);

Но со списком вы сделаете так:

MethodName(new List<int> {1, 2, 3, 4});

Синтаксис может быть немного более ясным в первом, чем последний. Это полезно, когда у вас есть только один параметр для перехода:

// params
MethodName(1);

// List
MethodName(new List<int> {1});

Ответ 6

params - это языковая конструкция для функций с переменным числом параметров. Это похоже на спецификатор C elipses - т.е. printf(char* fmt, ...). Язык поддерживает эту операцию, может также использовать ее, особенно если это упрощает чтение кода.

Ответ 7

Лично я пропустил бы параметры. Меня укусили один или два раза. Как? Позвольте мне объяснить.

Вы пишете открытый метод с этой сигнатурой:

public static void LogInUser(string username, string password, params string[] options)

Вы тестируете его, он работает, его выполняет... и другая сборка/приложение вызывает вашу функцию.

Теперь, через месяц, вы хотите изменить свою подпись, чтобы добавить роль пользователя:

public static void LogInUser(string username, string password, string role, params string[] options)

О, как все изменилось для чего-либо, вызывающего ваш метод.

LogInUser("[email protected]", "zz", "Admin", "rememberMe", "800x600");

Ответ 8

Основное различие между двумя, которые я вижу, заключается в том, что количество параметров, переданных в метод, устанавливается во время компиляции с использованием params, а при List<T> оно зависит от списка, переданного во время выполнения.

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

params помогает на фронте читабельности и находится как можно ближе к необязательному параметру, который вы собираетесь использовать в С#. Я бы использовал реализацию List<T> лично, если мне нужно было использовать неизвестное количество параметров в любой точке.

Изменить: просто заметили ваши изменения в отношении проблем с производительностью. В этой теме я не уверен, хотя, если вы могли бы ожидать большого количества "параметров", используя List<T>, тогда как params имеет ограничение безопасности, из-за того, что они должны быть закодированы.

Ответ 9

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

(Учитывая, что программисты стоят гораздо больше, чем компьютеры, почему вы думаете о какой-либо другой производительности).