Подтвердить что ты не робот

Код возврата или выход?

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

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

  • a 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)

что является предпочтительным и почему?

4b9b3361

Ответ 1

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

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

Tuple<SftpResult, ArrayList> GetFileList(string directory)

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

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

Ответ 2

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

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.

Ответ 3

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

Ответ 4

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

Ответ 5

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

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

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

Ответ 6

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

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

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) { ... }
}
... 

Ответ 7

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