Как обеспечить ошибку компиляции при изменении подписи при использовании ключевого слова "params"
У меня есть такой метод:
public void Foo(params string[] args) {
bar(args[0]);
bar(args[1]);
}
Новые требования приводят к таким изменениям:
public void Foo(string baz, params string[] args) {
if("do bar".Equals(baz)) {
bar(args[0]);
bar(args[1]);
}
}
Проблема в том, что, хотя я и изменил сигнатуру метода, ошибок компиляции не происходит, что, конечно, правильно, но я хочу, чтобы при каждом вызове были ошибки компиляции Foo
метод, где аргумент baz
не было указано. То есть, если вызов Foo
до изменения было это:
Foo(p1,p2); //where p1 and p2 are strings
теперь он должен быть таким:
Foo(baz,p1,p2);
Если это не будет изменено таким образом, p1
будет назначен на baz
и массив параметров args
будет иметь длину 1 и OutOfBounds
исключение будет брошено.
Каков наилучший способ изменить подпись и убедиться, что весь вызывающий код обновляется соответствующим образом? (Реальный сценарий где Foo
живет в сборке, совместно используемой многими проектами, автоматически созданными на сервере сборки. Таким образом, ошибка компиляции будет простым способом обнаружить весь код, к которому нужно прикоснуться, чтобы учесть изменения.)
Изменить: Как отметил Даниэль Манн и другие, приведенный выше пример предполагает, что я не должен использовать params вообще. Поэтому я должен объяснить, что в моем примере с реальным миром аргументы args не всегда должны иметь два элемента, поскольку логика в Foo касается аргументов, которые могут содержать любое количество элементов. Итак, скажем, это Foo:
public void Foo(string baz, params string[] args) {
if("do bar".Equals(baz)) {
int x = GetANumberDynamically();
for(int i = 0; i<x; i++)
bar(args[i]);
}
}
2 ответа
Вот решение. Не меняйте прежнюю сигнатуру метода, просто добавьте Obsolete
атрибут с указанием обоих аргументов.
[Obsolete("Use Foo(string, params string[]) version instead of this", true)]
public void Foo(params string[] args) {
bar(args[0]);
bar(args[1]);
}
Затем создайте новый метод с новой подписью.
public void Foo(string baz, params string[] args) {
if("do bar".Equals(baz)) {
bar(args[0]);
bar(args[1]);
}
}
Второй аргумент в Obsolete
Атрибут обеспечивает ошибку компиляции. Без этого это просто вызывает предупреждение компиляции. Более подробная информация об атрибуте доступна на MSDN.
РЕДАКТИРОВАТЬ:
Основываясь на обсуждении в комментариях ниже, Даниэль Манн предложил интересную проблему.
Это не решило бы проблему. Что если вы называете Foo("a", "b")? В этом случае он по-прежнему будет вызывать устаревший метод только с двумя аргументами и вызывать ту же проблему.
Я бы посоветовал проверить, есть ли более одного аргумента, переданного через args
перед звонком bar
,
Самое простое решение - не использовать params
Ключевое слово, если у вас есть необходимые параметры.
Очевидно, вы ожидаете args
содержать как минимум два параметра. Можно с уверенностью сказать, что это необходимо. Почему бы не иметь такую сигнатуру метода?
public void Foo(string baz, string requiredArgument1, string requiredArgument2, params string[] optionalArguments)
Это устраняет двусмысленность: это всегда потребует как минимум 3 аргумента.
Другой вариант, о котором я даже не задумывался по какой-то причине, - использовать именованные параметры. Очевидно, что весь ваш код должен был бы делать это явно, но вы могли бы сделать это:
Foo(baz: "bar", args: new [] {"a", "b", "c"});