Необязательные аргументы. Преимущества. Примеры применения необязательных аргументов. «Неоднозначность» в необязательных аргументах

Необязательные аргументы. Преимущества. Примеры применения необязательных аргументов. «Неоднозначность» в необязательных аргументах


Содержание



1. Что представляют собой необязательные аргументы и необязательные параметры?

В объявлении метода часть его параметров может получать значение по умолчанию. Параметр, который получает значение по умолчанию, называется необязательный параметр. Метод, который в объявлении содержит необязательные параметры, может вызваться без указания аргументов, которые соответствуют этим параметрам. Аргументы, которые передаются в метод и соответствуют необязательным параметрам, называются необязательными аргументами.

Таким образом, аргументы, которые передаются в метод, делятся на обязательные и необязательные.

Общая форма указания необязательного аргумента в перечне параметров метода имеет вид:

type parametr_name = const_value

где

  • type – тип необязательного параметра;
  • parameter_name – имя параметра, который соответствует необязательному аргументу при вызове метода;
  • const_value – константное значение по умолчанию, которое присваивается необязательному параметру.

Общая форма метода, который содержит один необязательный параметр, имеет следующий вид:

access return_type MethodName(type parameter_name = const_value)
{
  // ...
}

где

  • access – модификатор доступа к методу (private, protected, public);
  • return_type – тип, возвращаемый методом;
  • MethodName – имя метода;
  • parameter_name – имя параметра, который соответствует аргументу по умолчанию;
  • const_value – значение по умолчанию, присваиваемое параметру с именем parameter_name в случае, если вызвать метод MethodName() без параметров.

После такого объявления, вызов метода MethodName() можно осуществлять двумя способами:

  • с указанием заданного аргумента явным образом;
  • без указания аргумента. В этом случае, параметру parameter_name будет присвоенное значение по умолчанию value.

 

2. Преимущества применения необязательных аргументов

Использование необязательных аргументов дает следующие преимущества:

  • не нужно вводить дополнительные «перегруженные» реализации метода;
  • упрощается вызов сложных методов или конструкторов класса. Аргументы, которые не указываются при вызове такого метода, получают значение по умолчанию.

 

3. Примеры объявления и вызова методов, которые содержат необязательные аргументы

Пример 1. Метод, который определяет объем шара. Метод получает один входной параметр (радиус шара), который есть необязательным аргументом.

// метод, который содержит необязательный аргумент
double SphereVolume(double radius = 1.0)
{
  return 4.0 / 3.0 * 3.1415 * radius * radius * radius;
}

После такого объявления, метод можно вызвать двумя способами:

  • без использования явно заданного аргумента;
  • с использованием явно заданного аргумента.

Нижеследующий программный код демонстрирует вызов метода разными способами

// Продемонстрировать вызов метода SphereVolume
double vol;

// вызов метода без явно заданного (необязательного) аргумента
vol = SphereVolume(); // vol = 4.188667

// вызов метода с явно заданным аргументом
vol = SphereVolume(3.0); // vol = 113.094

Как видно из вышеприведенного кода, первый раз метод SphereVolume() вызывается без явно заданного аргумента. В этом случае, в метод ничего не передается, а внутренний параметр radius получает значение по умолчанию -1.0, что было задано при объявлении метода.

Второй раз происходит вызов метода

vol = SphereVolume(3.0);

В этом случае, в метод передается явным образом заданный аргумент 3.0. Формальный параметр метода radius получает значение аргумента равное 3.0. Значение по умолчанию заменяется новым значением.

Пример 2. Реализация метода, который получает четыре необязательных параметра.

Метод может получать любое количество необязательных параметров.
Ниже приведена реализация метода LengthLine(), который определяет длину отрезка. Метод получает координаты точек:

  • x1, y1 – координаты первой точки отрезка;
  • x2, y2 – координаты второй точки отрезка.
// метод определяет длину отрезка
static float LineSegment(float x1 = 0, float y1 = 0, float x2 = 1, float y2 = 1)
{
  float length;
  length = (float)Math.Sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
  return length;
}

Использование метода в другом программном коде

// Продемонстрировать вызов метода LineSegment
float len;

// вызов метода без явно заданных аргументов
// аргументы x1, y1, x2, y2 - необязательные
len = LineSegment(); // x1=0, y1=0, x2=1, y2=1; len = 1.414214

// вызов метода с 1 явно заданным аргументом
// аргументы x1, y1, x2 - необязательные
len = LineSegment(3); // x1=3, y1=0, x2=1, y2=1; len = 2.236068

// вызов метода с 2 явно заданными аргументами
// аргументы x2, y2 - необязательные
len = LineSegment(-1, 4); // x1=-1, y1=4, x2=1, y2=1; len = 3.605551

 

4. Примеры реализации и использования классов, которые содержат конструкторы с необязательными аргументами

Пример 1. Задан класс Triangle, реализующий треугольник на плоскости.
В классе реализованы:

  • шесть общедоступных переменных с именами x1, y1, x2, y2, x3, y3. Переменные реализуют координаты точек, которые образовывают треугольник;
  • конструктор, который получает необязательные аргументы.

Листинг класса Triangle следующий:

// класс, реализующий треугольник
class Triangle
{
  // координаты точек, которые образовывают треугольник
  public double x1, y1, x2, y2, x3, y3;

  // конструктор класса, получает необязательные аргументы
  public Triangle(double x1 = 0, double y1 = 0, double x2 = 1, double y2 = 1, double x3 = -1, double y3 = -1)
  {
    // инициализация переменных класса
    this.x1 = x1; this.y1 = y1;
    this.x2 = x2; this.y2 = y2;
    this.x3 = x3; this.y3 = y3;
  }
}

Использование класса в другом программном коде может быть следующим:

// Демонстрация использования необязательных аргументов в конструкторе класса Triangle
// 1. Передать все аргументы явным образом в конструктор класса
Triangle tr1 = new Triangle(2, 3, -1, -3, 0, 5); // x1=2, y1=3, x2=-1, y2=-3, x3=0, y3=5

// 2. Передать 5 аргументов явным образом, аргумент y3 - необязательный аргумент
Triangle tr2 = new Triangle(1, 2, 0, 0, -4); // x1=1, y1=2, x2=0, y2=0, x3=-4, y3=-1

// 3. Передать 2 аргумента явным образом, аргументы x2, y2, x3, y3 - необязательные
Triangle tr3 = new Triangle(8, 9); // x1=8, y1=9, x2=1, y2=1, x3=-1, y3=-1

При создании объекта класса Triangle вызывается конструктор, который содержит параметры по умолчанию. В первом случае создается объект tr1. При создании объекта вызывается конструктор, которому передаются все 6 явным образом заданных аргументов (обязательных аргументов).
Во втором случае, при создании объекта tr2 вызывается конструктор, в котором 5 аргументов задаются явным образом и один (y3) есть необязательным аргументом. В методе необязательному аргументу y3 присваивается значение по умолчанию -1.
В третьем случае создается объект с именем tr3. При создании этого объекта конструктор получает значение двух явно заданных аргументов, значение которых присваиваются параметрам-переменным x1, y1. Другие 4 параметра конструктора получают значение по умолчанию, в данном случае x2=1, y2=1, x3=-1, y3=-1.

Пример 2. Пусть задан класс ArrayInt, реализующий массив целых чисел. В классе объявляется конструктор, содержащий необязательные аргументы.

class ArrayInt
{
  int[] A;

  // конструктор с необязательным аргументом n
  public ArrayInt(int n = 0)
  {
    A = null;
    if (n == 0) return;

    // выделить память под массив A
    A = new int[n];

    // обнулить массив
    for (int i = 0; i < A.Length; i++)
      A[i] = 0;
  }

  // методы доступа к массиву
  public int[] Get() { return A; }

  public void Set(int[] AA)
  {
    A = new int[AA.Length];
    for (int i = 0; i < A.Length; i++)
      A[i] = AA[i];
  }
}

Использование класса в другом программном коде

// вызов конструкторов с необязательными аргументами
ArrayInt ai1 = new ArrayInt(); // вызов конструктора с указанием необязательного аргумента
ArrayInt ai2 = new ArrayInt(5); // вызов конструктора с обязательным аргументом

// проверка
int n_items;

if (ai1.Get() != null)
  n_items = ai1.Get().Length;
else
  n_items = 0; // n_items = 0

n_items = ai2.Get().Length; // n_items = 5

 

5. Какие требования накладываются синтаксисом C# на порядок объявления необязательных аргументов в методе?

Согласно синтаксису C#, при использовании в методе необязательных аргументов нужно придерживаться следующего правила:

  • объявление необязательных параметров должно быть реализовано справа от обязательных.

 

6. Сколько необязательных параметров может быть объявлено в методе?

В методе может быть объявлено любое количество необязательных параметров. Главное, чтобы их объявление следовало справа от объявления обязательных параметров.

 

7. В каких элементах языка программирования C# можно использовать необязательные аргументы?

Необязательные аргументы можно использовать в:

  • методах классов (в т.ч. и конструкторах);
  • конструкторах классов;
  • делегатах.

 

8. Пример использования необязательных аргументов в делегатах

Делегаты также как и методы могут принимать необязательные аргументы. В этом случае синтаксис объявления делегата такой же как и синтаксис объявления метода.

Пусть задан делегат TInt, что получает и возвращает целочисленное значение. Для параметра делегата задается значение по умолчанию, которое равно 1. Также задаются 3 метода, сигнатура которых совпадает с сигнатурой делегата.

// объявление типа делегата TInt, получающего значение по умолчанию = 1
delegate int TInt(int d = 1);

// метод, который умножает целое число на 2
static int Mult2(int d)
{
  return d * 2;
}

// метод, который вычисляет квадрат целого числа
static int Square(int d)
{
  return d * d;
}

// метод, умножающий число на 5
static int Mult5(int d)
{
  return d * 5;
}

Использование делегата типа TInt, получающий необязательный аргумент может быть следующим:

TInt t; // объявить делегат типа TInt

// создать цепочку вызовов методов
t = Mult2; // t => Mult2
t += Mult5; // t => Mult2 => Mult5

// вызвать последовательно методы
int result;

// вызов методов Mult2(), Mult5() с необязательным аргументом
result = t(); // result = 5

// вызов методов Mult2(3), Mult5(3) с явно заданным аргументом
result = t(3); // result = 15

 

9. Что значит термин «неоднозначность» при вызове необязательных аргументов? Пример

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

Например. Пусть заданы два «перегруженых» метода Sum(), получающие необязательные аргументы. В обоих методах первый аргумент с именем a есть обязательным.

int Sum(int a, int b = 1, int c = 2)
{
  return a+b+c;
}

int Sum(int a, double b = 2.0, double c = 3.0)
{
  return (int)(a + b + c);
}

Если написать следующий код вызова метода Sum()

int t;

// неоднозначный вызов, компилятор не знает какой метод вызвать
t = Sum(5);

то компилятор выдаст сообщение об ошибке:

The call is ambiguous between the following methods or properties:
'Sum(int, int, int)' and 'Sum(int, double, double)'

что значит

Вызов есть неопределенным для следующих методов
Sum(int, int, int) и Sum(int, double, double)

 


Связанные темы