Методы перегрузки или нет? - PullRequest
4 голосов
/ 14 февраля 2011

У меня есть два метода (killZombie), которые обрабатывают случаи, когда у вас есть один аргумент (строка) или более одного аргумента (строка []). Поскольку они делают то же самое, я создал другой метод с именем killAZombie, который используется двумя другими методами. У меня проблема в том, что метод killAZombie назван ... ну как-то странно. С этой проблемой сталкиваются и другие люди? Каков наилучший способ решить эту проблему и назвать мой метод «KillAZombie» как-то еще, более четко отличающийся от «killZombie»

public void killZombie(string zombieLocation){
    killAZombie(zombieLocation);
}

public void killZombie(string[] zombieLocations){
    foreach(string zombieLocation in zombieLocations){
        killAZombie(zombieLocation);
    }
}

public void killAZombie(string zombieLocation){
    //Kills a zombie at specified location
}

Еще один способ увидеть, что эта проблема решается, - вместо того, чтобы перегрузить «killZombie», используйте два разных метода:

public void killZombie(string zombieLocation){
    //Kills a zombie at specified location
}

public void killZombies(string[] zombieLocations){
    foreach(string zombieLocation in zombieLocations){
        killZombie(zombieLocation);
    }
}

Таким образом, у нас есть только два метода, которые легче понять, но тогда метод не перегружен. На мой взгляд, неплохо иметь перегруженные методы (это просто означает, что методов меньше, меньше беспорядка), поэтому я не уверен насчет этого решения. Мне было бы интересно услышать, как лучше решить эту проблему, спасибо!

Добавление:

Мой метод на самом деле принимает 4 аргумента, поэтому они будут в конце. Переменная params является наиболее важной, поэтому ее использование в качестве последнего аргумента, заставляющего работать params, кажется довольно неуклюжим. Является ли мое беспокойство по поводу того, чтобы последний самый важный аргумент был последним, достаточно законным, чтобы разделить методы на KillZombie и KillZombies, или параметры все еще являются правильным способом сделать что-то?

Ответы [ 6 ]

6 голосов
/ 14 февраля 2011

Вот несколько идей.

Во-первых, соглашение C # для открытых методов состоит в том, чтобы использовать их как прописные: "KillZombie", а не "killZombie".

Вы можете сделать это только одним методом, если хотите. Вот метод, который занимает одно или несколько местоположений. Вызывающий абонент может просто предоставить список: KillZombies(location1, location2, location3);

private void KillOneZombie(string location) { ... }
public void KillZombies(string location, params string[] additionalLocations)
{
    KillOneZombie(location);
    if (additionalLocations == null) return;
    foreach(string additionalLocation in additionalLocations)
        KillOneZombie(additionalLocation);
}

Если вы хотите иметь два метода, подумайте, чтобы один из них взял IEnumerable<string> вместо массива; таким образом, вызывающая сторона может передать список, запрос, массив, что угодно.

Ваш второй шаблон именования более стандартный: KillZombie и KillZombies.

Переменная params является наиболее важной, поэтому ее использование в качестве последнего аргумента, заставляющего работать params, кажется неуклюжим. Является ли мое беспокойство по поводу того, чтобы последний самый важный аргумент был последним, достаточно законным, чтобы разделить методы на KillZombie и KillZombies, или параметры все еще являются правильным способом сделать что-то?

Я бы подумал о том, как вы ожидаете, что метод будет использоваться. Рассмотрим для примера:

Console.WriteLine("User: {0} Score: {1}", user[i].Name, scores[i]);

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

object[] results = new object[] { user[i].Name, scores[i] };
Console.WriteLine("User: {0} Score: {1}", results);

хотя это совершенно законно. Если вы ожидаете, что ваш метод будет использоваться как Console.WriteLine, где будет передаваться различное количество параметров, но число параметров известно во время компиляции, тогда используйте params.

Если вы ожидаете, что он будет использоваться со вторым шаблоном - у кого-то есть массив местоположений - тогда не используйте params; создайте два метода, KillZombie и KillZombies, и пусть один из них получит IEnumerable из строк.

4 голосов
/ 14 февраля 2011

Последний из двух вариантов, вероятно, предпочтительнее в этом случае (учитывая, что присвоение имени функции подразумевает, что она работает с одним "зомби".

Тем не менее, вы также можете посмотреть ключевое слово params, просто чтобы знать, какие у вас есть варианты. Например, если бы вы назвали свою функцию просто Kill (и если в этом контексте имеет смысл это сделать), вы могли бы получить:

public void Kill(params string[] zombieNames)
{
    foreach(string name in zombieNames)
    {

    }
}

И вы можете назвать это несколькими способами:

Kill("Zoey");
Kill("Francis", "Zoey");

string[] survivors = { "Zoey", "Francis", "Bill", "Louis" };

Kill(names);

(Если, конечно, все ваши выжившие были превращены в зомби!)

Кроме того, в стилистическом коде C # обычно используются символы паскаля для имен функций (KillAZombie, а не killAZombie).

Редактировать для добавления

Да, порядок параметров - хотя он не имеет технической значимости - является важным фактором при разработке API, поэтому, если вы собираетесь использовать «менее важные» параметры, вам, вероятно, придется обойтись без params.

С учетом сказанного я буду придерживаться своей первоначальной рекомендации: так как функция названа (KillZombie против Kill), я бы придерживался двух версий только для того, чтобы ваше имя соответствовало параметрам. Я также предложил бы разрешить пользователю указывать IEnumerable<string> вместо массива. Это позволит разработчику передавать имена, используя все, что реализует IEnumerable<string>, , включая массив строк.

3 голосов
/ 14 февраля 2011

В этом случае я бы, вероятно, согласился на ваше второе предложение. KillZombie убивает одного зомби; KillZombies убивает нескольких зомби.

Другой вариант - использовать один метод с аргументом params:

KillZombies("foo");           // kill a single zombie
KillZombies("foo", "bar");    // kill multiple zombies

// ...

public void KillZombies(params string[] zombieLocations)
{
    foreach (string zombieLocation in zombieLocations)
    {
        // kills a zombie at specified location
    }
}

(Обратите внимание также, что стандартное соглашение об именах C # будет использовать KillZombie / KillZombies с заглавной буквой "K".)

2 голосов
/ 14 февраля 2011

Прежде всего, существует не только эти две альтернативы.

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

public void KillZombie(string zombieLocation){
    // Implement zombie killing logic here.
}

public void KillZombie(string[] zombieLocations){
    foreach(string zombieLocation in zombieLocations)
        KillZombie(zombieLocation);
}

Но в этом случае ярекомендовал бы иметь два разных метода.Конечно, они делают подобные вещи, но один берет зомби, а другой - один зомби.Имя метода должно отражать это.

Аналогично, класс .NET List имеет сходные методы Add и AddRange.

0 голосов
/ 14 февраля 2011

как насчет использования этого:

public void killZombies(string zombieLocation, params string[] zombieLocations){
    killZombie(zombieLocation);
    if(zombieLocations != null) {
        foreach(string zombieLocation in zombieLocations){
            killZombie(zombieLocation);
        }
    }
}

Вы можете пропустить одного или нескольких зомби.

[редактировать], как прокомментировано, это обновление запрещает убивать зомби

0 голосов
/ 14 февраля 2011

Ваш пример, к сожалению, неверен - вы также можете использовать массив params для разрешения вызовов типа KillZombies (location1, location2, location3).Массивы параметров допускают неопределенное количество параметров.

Тем не менее, это часто делается для более легкого использования.Если у вас есть 3 ovterload, потому что они все используются, то нет ничего плохого в том, чтобы их иметь, или?

Посмотрите на различные методы String.Format.

...