Код возврата или выходной параметр? - PullRequest
18 голосов
/ 10 сентября 2010

Я делаю метод для получения списка имен файлов с сервера, но у меня возникла проблема, на которую я не могу ответить.

Метод возвращает две вещи:

  • и SftpResult - это перечисление с различными кодами возврата.
  • список имен файлов.

Из этих трех подписей:

public static ArrayList GetFileList(string directory, out SftpResult result)

public static SftpResult GetFileList(string directory, out ArrayList fileNames)

public static SftpFileListResult GetFileList(string directory)

(где SftpFileListResult - составной объект SftpResult и ArrayList)

что предпочтительнее и почему?

Ответы [ 7 ]

32 голосов
/ 10 сентября 2010

Лично я предпочитаю последний вариант (хотя вместо ArrayList используется List<T> или ReadOnlyCollection<T>). out параметры - это в основном способ возврата нескольких значений, и обычно лучше инкапсулировать их.

Другой вариант в .NET 4 будет

Tuple<SftpResult, ArrayList> GetFileList(string directory)

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

(Если вы не используете .NET 4, вы всегда можете написать свой собственный тип Tuple.)

9 голосов
/ 10 сентября 2010

Я бы предпочел обернуть его в возвращаемый объект:

class FileResult
{
    public FileResult(SftpResult resultCode, IEnumerable<string> files)
    {
         ResultCode = resultCode;
         FileList = new List<string>(files);
    }
    public SftpResult ResultCode { get; private set; }
    public IEnumerable<string> FileList { get; private set; }
}

Чувствуется, что намного чище не использовать out.

4 голосов
/ 10 сентября 2010

Я предпочитаю окончательный вариант. Выходные параметры используются редко и могут удивлять / вводить в заблуждение некоторых. Создание составного объекта результата является чистым решением. Единственным недостатком является то, что вы должны создать класс исключительно для этой цели.

3 голосов
/ 10 сентября 2010

Я бы сказал третье, поскольку оно заключает в себе необходимую логику в одном месте Я могу только предположить, что методы возврата SftpResult и ArrayList должны быть закрытыми, а затем формировать внутреннюю логику составного объекта возврата.

2 голосов
/ 10 сентября 2010

Если вам нравятся проекты, в которых одна функция выполняет две функции, я бы использовал кортеж а-ля Джон или возвращаемый объект а-ля Фредрик.

Если вы хотите быть полностью ООПы в этом, вы можете позволить системе типов выполнить всю работу:

abstract class FtpResult { ... }
sealed class FileList : FtpResult { ... }
sealed class Error : FtpResult { ... }
...
sealed class FtpService
{
    ...
    public FtpResult GetFileList(string directory) { ... }
    ...
}
...
var result = service.GetFileList(dir);
var error = result as Error;
var list = result as FileList;
if (error != null) { ... }
else if (list != null)
{
    foreach(var name in list.Files) { ... }
}
... 
2 голосов
/ 10 сентября 2010

Я бы сделал это:

public static bool GetFileList(string directory, out SftpResult result, out ArrayList fileNames)

Так что нет никакой путаницы относительно того, что делает функция, а также я бы возвратил логическое значение, если GetFileList может завершиться ошибкой.

1 голос
/ 10 сентября 2010

Почему бы не предоставить все три?Я предпочитаю не использовать параметры в своих вызовах функций, но я могу оценить, что во многих случаях они необходимы.Если вы не знаете, какую подпись поддерживать, поддержите все три.В конечном счете, выбор остается за абонентом, и лучшее, что вы можете сделать, это предложить этот выбор.

...