我正在制作一个从服务器获取文件名列表的方法,但我遇到了一个我无法回答的问题。
该方法返回两件事:
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
的合成对象)
这是首选的,为什么?
答案 0 :(得分:32)
我个人更喜欢最后一个选项(尽管使用List<T>
或ReadOnlyCollection<T>
代替ArrayList
)。 out
参数基本上是一种返回多个值的方法,而通常更好地封装了这些值。
.NET 4中的另一个选项是
Tuple<SftpResult, ArrayList> GetFileList(string directory)
明确地说,“这个方法返回两件事......我已经为这个特殊情况将它们打包在一起了,但是不值得进一步封装它们:它们不值得在一个单独的类型中编写”。< / p>
(如果您不使用.NET 4,则可以随时编写自己的Tuple
类型。)
答案 1 :(得分:9)
我更愿意将它包装在一个返回对象中:
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
感觉更清洁。
答案 2 :(得分:4)
我更喜欢最后的选择。 Out参数很少使用,对某些人来说可能会让人感到惊讶/困惑。创建复合结果对象是一个干净的解决方案。唯一的缺点是您必须仅为此目的创建一个类。
答案 3 :(得分:3)
我会说第三个,因为它在一个位置封装了你需要的逻辑。我只能假设SftpResult和ArrayList返回方法应该是私有的,然后组成复合返回对象的内部逻辑。
答案 4 :(得分:2)
我会成功:
public static bool GetFileList(string directory, out SftpResult result, out ArrayList fileNames)
因此,如果GetFileList失败,那么函数的作用就不会产生混淆,而且我会返回一个bool。
答案 5 :(得分:2)
如果你喜欢设计,其中一个函数做两件事,那么我会使用一个元组一个Jon或一个返回对象一个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) { ... }
}
...
答案 6 :(得分:1)
为什么不提供全部三个?我不喜欢在我的函数调用中输出参数,但我很欣赏它在很多时候都需要它们。如果您不知道支持哪个签名,那么支持所有三个。最终,选择是在来电者的一边,你可以做的最好的事情是提供这种选择。