Static void OptArgMeth(int alpha, int beta)
Static void OptArgMeth(int alpha, int beta, int gamma)
Эти перегружаемые варианты метода OptArgMeth () позволяют вызывать его с од
ним, двумя или тремя аргументами. (Если значения параметров beta и gamma не передаются, то они предоставляются в теле перегружаемых вариантов данного метода.) Безусловно, в такой реализации функциональных возможностей метода OptArgMeth () с помощью перегрузки нет ничего дурного. Но в данном случае целесообразнее все же воспользоваться необязательными аргументами, хотя такой подход не всегда оказывается более совершенным, чем перегрузка метода.
Необязательные аргументы и неоднозначность
При использовании необязательных аргументов может возникнуть такое затруднение, как неоднозначность. Нечто подобное может произойти при перегрузке метода с необязательными параметрами. В некоторых случаях компилятор может оказаться не в состоянии определить, какой именно вариант метода следует вызывать, когда необязательные аргументы не заданы. В качестве примера рассмотрим два следующих варианта метода OptArgMeth ().
static void OptArgMeth(int alpha, int beta=10, int gamma = 20) {
Console.WriteLine("Это аргументы alpha, beta и gamma: " + alpha + " " + beta + " " + gamma);
}
static void OptArgMeth(int alpha, double beta=10.0, double gamma =20.0) {
Console.WriteLine("Это аргументы alpha, beta и gamma: " + alpha + " " + beta + " " + gamma);
}
Обратите внимание на то, что единственное отличие в обоих вариантах рассматриваемого здесь метода состоит в типах параметров beta и gamma, которые оказываются необязательными. В первом варианте оба параметра относятся к типу int, а во втором — к типу double. С учетом этих вариантов перегрузки метода OptArgMeth () следующий его вызов приводит к неоднозначности.
OptArgMeth(1); // Ошибка из-за неоднозначности!
Этот вызов приводит к неоднозначности потому, что компилятору неизвестно, какой именно вариант данного метода использовать: тот, где параметры beta и gamma имеют тип int, или же тот, где они имеют тип double. Но самое главное, что конкретный вызов метода OptArgMeth () может привести к неоднозначности, даже если она и не присуща его перегрузке.
В связи с тем что перегрузка методов, допускающих применение необязательных аргументов, может привести к неоднозначности, очень важно принимать во внимание последствия такой перегрузки. В некоторых случаях, возможно, придется отказаться от применения необязательных аргументов, чтобы исключить неоднозначность и тем самым предотвратить использование метода непреднамеренным образом.
Практический пример использования необязательных аргументов
Для того чтобы показать на практике, насколько необязательные аргументы упрощают вызовы некоторых типов методов, рассмотрим следующий пример программы. В этой программе объявляется метод Display (), выводящий на экран символьную строку полностью или частично.
// Использовать необязательный аргумент, чтобы упростить вызов метода.
using System;
class UseOptArgs {
// Вывести на экран символьную строку полностью или частично, static void Display(string str, int start = 0, int stop = -1) {
if(stop < 0)
stop = str.Length;
// Проверить условие выхода за заданные пределы, if(stop > str.Length | start > stop | start < 0) return;
for (int i=start; i < stop; i++)
Console.Write(str[i]);
Console.WriteLine ();
}
static void Main() {
Display("это простой тест");
Display("это простой тест", 12);
Display("3TO простой тест", 4, 14);
}
}
Выполнение этой программы дает следующий результат.
это простой тест тест
простой те
Внимательно проанализируем метод Display (). Выводимая на экран символьная строка передается в первом аргументе данного метода. Это обязательный аргумент, а два других аргумента — необязательные. Они задают начальный и конечный индексы для вывода части символьной строки. Если параметру stop не передается значение, то по умолчанию он принимает значение -1, указывающее на то, что конечной точкой вывода служит конец символьной строки. Если же параметру start не передается значение, то по умолчанию он принимает значение 0. Следовательно, в отсутствие одного из необязательных аргументов символьная строка выводится на экран полностью. В противном случае она выводится на экран частично. Это означает, что если вызвать метод Display () с одним аргументом (т.е. с выводимой строкой), то символьная строка будет выведена на экран полностью. Если же вызвать метод Display () с двумя аргументами, то на экран будут выведены символы, начиная с позиции, определяемой аргументом start, и до самого конца строки. А если вызвать метод Display () с тремя аргументами, то на экран будут выведены символы из строки, начиная с позиции, определяемой аргументом start, и заканчивая позицией, определяемой аргументом stop.
Несмотря на всю простоту данного примера, он, тем не менее, демонстрирует значительное преимущество, которое дают необязательные аргументы. Это преимущество заключается в том, что 1 при вызове метода можно указывать только те аргументы, которые требуются. А передавать явным образом устанавливаемые по умолчанию значения не нужно.
Прежде чем переходить к следующей теме, остановимся на следующем важном моменте. Необязательные аргументы оказываются весьма эффективным средством лишь в том случае, если они используются правильно. Они предназначены для того, чтобы метод выполнял свои функции эффективно, а пользоваться им можно было бы просто и удобно. В этом отношении устанавливаемые по умолчанию значения всех аргументов должны упрощать обычное применение метода. В противном случае необязательные аргументы способны нарушить структуру кода и ввести в заблуждение тех, кто им пользуется. И наконец, устанавливаемое по умолчанию значение необязательного параметра не должно наносить никакого вреда. Иными словами, неумышленное использование необязательного аргумента не должно приводить к необратимым, отрицательным последствиям. Так, если забыть указать аргумент при вызове метода, то это не должно привести к удалению важного файла данных!
Именованные аргументы
Еще одним средством, связанным с передачей аргументов методу, является именованный аргумент. Именованные аргументы были внедрены в версии C# 4.0. Как вам должно быть уже известно, при передаче аргументов методу порядок их следования, как правило, должен совпадать с тем порядком, в котором параметры определены в самом методе. Иными словами, значение аргумента присваивается параметру по его позиции в списке аргументов. Данное ограничение призваны преодолеть именованные аргументы. Именованный аргумент позволяет указать имя того параметра, которому присваивается его значение. И в этом случае порядок следования аргументов уже не имеет никакого значения. Таким образом, именованные аргументы в какой-то степени похожи на упоминавшиеся ранее инициализаторы объектов, хотя и отличаются от них своим синтаксисом.