Зачем использовать ключевое слово params?

Я знаю, что это основной вопрос, но я не мог найти ответа.

Зачем его использовать? если вы напишете функцию или метод, который ее использует, при ее удалении код будет работать отлично, 100% без него. Например:

С параметрами:

static public int addTwoEach(params int[] args)
{
    int sum = 0;
    foreach (var item in args)
        sum += item + 2;
    return sum;
}

Без параметров:

static public int addTwoEach(int[] args)
{
    int sum = 0;
    foreach (var item in args)
       sum += item + 2;
    return sum;
}

Ответ 1

С помощью params вы можете вызвать свой метод следующим образом:

addTwoEach(1, 2, 3, 4, 5);

Без params вы не можете.

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

addTwoEach(new int[] { 1, 2, 3, 4, 5 });

То есть params позволяет использовать ярлык при вызове метода.

Не связанный, вы можете резко сократить свой метод:

public static int addTwoEach(params int[] args)
{
    return args.Sum() + 2 * args.Length;
}

Ответ 2

Использование params позволяет вам вызвать функцию без аргументов. Без params:

static public int addTwoEach(int[] args)
{
    int sum = 0;

    foreach (var item in args)
    {
        sum += item + 2;
    }

    return sum;
}

addtwoEach(); // throws an error

Сравните с params:

static public int addTwoEach(params int[] args)
{
    int sum = 0;

    foreach (var item in args)
    {
        sum += item + 2;
    }

    return sum;
}

addtwoEach(); // returns 0

Как правило, вы можете использовать параметры, когда количество аргументов может варьироваться от 0 до бесконечности и использовать массив, когда количество аргументов варьируется от 1 до бесконечности.

Ответ 3

Он позволяет вам добавить столько же параметров базового типа в ваш вызов, сколько захотите.

addTwoEach(10, 2, 4, 6)

тогда как во второй форме вы должны использовать массив как параметр

addTwoEach(new int[] {10,2,4,6})

Ответ 4

Ключевое слово params опасно, если после кодирования вызовов метода

  1. кто-то случайно/преднамеренно удаляет один/несколько обязательных параметров из подписи метода, и
  2. один/несколько обязательных параметров непосредственно перед params Параметр до изменения подписи был совместим с типом params Params,

эти вызовы будут продолжать компилироваться с одним/несколькими выражениями, ранее предназначенными для требуемых параметров, которые рассматриваются как необязательный params. Я только что столкнулся с наихудшим из возможных случаев: params имел тип Type object[].

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

Для меня это не стоит ярлыка. (Type)[] без params будет работать с 0 до бесконечности # параметров без необходимости переопределения. В худшем случае вам придется добавить , new (Type) [] {} в Calls, если он не применяется.

Кстати, имхо, самая безопасная (и наиболее читаемая практика) заключается в:

  1. передать через именованные параметры (что мы можем теперь сделать даже в С# ~ 2 десятилетия после того, как мы могли бы в VB; P) (потому что:

    1.1. это единственный способ, который гарантирует предотвращение непреднамеренных значений, передаваемых в параметры после изменения порядка параметров, типа совместимости и/или количества после кодирования вызовов,

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

    1.3. он избегает необходимости считать запятые и переходить назад и вперед из Call to Signature, чтобы увидеть, какое выражение передается для какого параметра, и

    1.3.1. Кстати, одной этой причины должно быть достаточно (с точки зрения избежания частых нарушений принципа DRY, подверженных ошибкам, только для того, чтобы прочитать код, не говоря уже о том, чтобы изменить его, а также изменить), но эта причина может быть экспоненциально более важной, если есть одна/Передается больше выражений, которые сами содержат запятые, то есть ссылки на многомерный массив или вызовы функций с несколькими параметрами. В этом случае вы даже не можете использовать (который, даже если бы вы могли добавить дополнительный шаг для каждого параметра на вызов метода), функцию "Найти все вхождения" в функции выбора в вашем редакторе, чтобы автоматизировать подсчет запятых для вас.

    1.4. если вы должны использовать Необязательные параметры (params или нет), это позволяет вам искать Звонки, где определенный Необязательный параметр пропущен (и, следовательно, скорее всего, нет или, по крайней мере, имеет возможность не быть значением по умолчанию),

(ПРИМЕЧАНИЕ. Причины 1.2. И 1.3. Могут облегчить и уменьшить вероятность ошибок даже при кодировании начальных вызовов, не говоря уже о том, когда вызовы должны быть прочитаны и/или изменены.))

а также

  1. сделайте так ОДИН - ПАРАМЕТР - НА - ЛИНИЮ для лучшей читаемости (потому что:

    2.1. это менее загромождено, и

    2.2. он избегает необходимости прокручивать вправо и назад влево (и делает это ДОПОЛНИТЕЛЬНО, поскольку большинство смертных не может прочитать левую часть нескольких строк, прокрутить вправо и прочитать правую часть)).

    2,3. это соответствует "лучшей практике", в которую мы уже вошли для операторов присваивания, потому что каждый переданный параметр по сути является оператором присваивания (присваивая значение или ссылку на локальную переменную). Точно так же, как те, кто следит за последней "Лучшей практикой" в стиле кодирования, не будут мечтать о кодировании нескольких операторов присваивания на строку, мы, вероятно, не должны (и однажды "Лучшая практика" догонит мою "гениальность"; P) ) сделать это при передаче параметров.

ЗАМЕЧАНИЯ:

  1. Передача переменных, чьи имена отражают параметры, не помогает, когда:

    1.1. вы передаете литеральные константы (т.е. простые 0/1, false/true или null, для которых даже в "Best Practices" может не потребоваться использование именованной константы, и их назначение не может быть легко определено из имени метода),

    1.2. метод является значительно более низким уровнем/более общим, чем вызывающий, так что вы не захотите/не сможете назвать свои переменные такими же/похожими на параметры (или наоборот), или

    1.3. вы переупорядочиваете/заменяете параметры в подписи, что может привести к тому, что предыдущие вызовы все еще компилируются, потому что типы все еще совместимы.

  2. Наличие функции автоматической обертки, такой как VS, устраняет только ОДНУ (# 2.2) из 8 причин, которые я привел выше. До VS 2015 года это НЕ делало авто-отступ (!?! Действительно, MS?!?), Что увеличивает серьезность причины # 2.1.

В VS должна быть опция, которая генерирует фрагменты вызова метода с именованными параметрами (по одному на строку, конечно, P) и опцией компилятора, которая требует именованных параметров (аналогично концепции Option Explicit в VB, который, между прочим, требовался совсем недавно) в равной степени возмутительно, но в настоящее время требуется "" передовой опыт "). На самом деле, "назад в мои дни";), в 1991 году, за несколько месяцев до моей карьеры, даже до того, как я использовал (или даже видел) язык с именованными параметрами, у меня был анти-овец/"просто потому, что вы можете, не означает, что вы не должны "/не слепо" резать концы жаркого "достаточно, чтобы смоделировать его (используя встроенные комментарии), не видя, чтобы кто-то это делал. Отсутствие необходимости использовать именованные параметры (а также другой синтаксис, сохраняющий "драгоценные" нажатия клавиш исходного кода) является пережитком эры перфокарт, когда началось большинство этих синтаксисов. Этому нет оправдания современному оборудованию и IDE, а также гораздо более сложному программному обеспечению, где читаемость намного, Гораздо важнее. "Код читается гораздо чаще, чем пишется". Пока вы не дублируете не-автоматически обновляемый код, каждое сохраненное нажатие клавиш, вероятно, будет стоить экспоненциально дороже, если кто-то (даже вы) попытаетесь прочитать его позже.

Ответ 5

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

// Call params method with one to four integer constant parameters.
//
int sum0 = addTwoEach();
int sum1 = addTwoEach(1);
int sum2 = addTwoEach(1, 2);
int sum3 = addTwoEach(3, 3, 3);
int sum4 = addTwoEach(2, 2, 2, 2);

Ответ 6

params также позволяет вызывать метод с одним аргументом.

private static int Foo(params int[] args) {
    int retVal = 0;
    Array.ForEach(args, (i) => retVal += i);
    return retVal;
}

то есть. Foo(1); вместо Foo(new int[] { 1 });. Может быть полезно для сокращений в сценариях, где вам может потребоваться передать только одно значение, а не весь массив. Он по-прежнему обрабатывается одинаково в методе, но дает некоторые конфеты для вызова таким образом.

Ответ 7

Добавление самого ключевого слова params показывает, что вы можете передавать несколько параметров при вызове этого метода, который невозможен без его использования. Чтобы быть более конкретным:

static public int addTwoEach(params int[] args)
{
    int sum = 0;

    foreach (var item in args)
    {
        sum += item + 2;
    }

    return sum;
}

Когда вы вызовете метод выше, вы можете вызвать его одним из следующих способов:

  • addTwoEach()
  • addTwoEach(1)
  • addTwoEach(new int[]{ 1, 2, 3, 4 })

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

Ответ 8

Еще одна важная вещь должна быть выделена. Лучше использовать params потому что это лучше для производительности. Когда вы вызываете метод с params и ничего не передаете ему:

public void ExampleMethod(params string[] args)
{
// do some stuff
}

вызов:

ExampleMethod();

Затем новые версии .Net Framework делают это (из .Net Framework 4.6):

ExampleMethod(Array.Empty<string>());

Этот объект Array.Empty может быть повторно использован платформой позже, поэтому нет необходимости делать избыточные выделения. Эти распределения будут происходить, когда вы вызываете этот метод следующим образом:

 ExampleMethod(new string[] {});