返回码还是输出参数?
Posted
技术标签:
【中文标题】返回码还是输出参数?【英文标题】:Return code or out parameter? 【发布时间】:2011-04-10 17:18:08 【问题描述】:我正在制作一种从服务器获取文件名列表的方法,但我遇到了一个我无法回答的问题。
该方法返回两件事:
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
的复合对象)
哪个是首选,为什么?
【问题讨论】:
SftpResult 的目的是什么?如果它应该解释调用失败的原因,也许你应该抛出一个异常。 考虑到我所做的只是报告状态,我认为这太过分了。如果它失败,这不是一个严重的问题,而且我真的不需要仅仅因为他们输入了错误的目录而展开堆栈。我只是返回一个 DirectoryNotFound 并继续我的业务 :-) 考虑放弃使用 ArrayList 转而使用 IEnumerablereturn new ReadOnlyCollection<string>((List<string>)(IEnumerable<string>)Connection.SshConnection.GetFileList(directory));
?? Connection.SshConnection.GetFileList(directory)
部分返回 ArrayList
@rmx Enumerable.Cast 和 List.AsReadOnly 可以在这里提供帮助 return ...GetFileList(directory).Cast<string>().ToList().AsReadOnly();
【参考方案1】:
我个人更喜欢最后一个选项(尽管使用List<T>
或ReadOnlyCollection<T>
而不是ArrayList
)。 out
参数基本上是一种返回多个值的方式,一般最好将它们封装起来。
.NET 4 中的另一个选项是
Tuple<SftpResult, ArrayList> GetFileList(string directory)
这明确地说,“这个方法返回两个东西......我已经为你把它们打包在一起,但不值得进一步封装它们:它们不值得组合成一个单独的类型”。
(如果您不使用 .NET 4,您始终可以编写自己的 Tuple
类型。)
【讨论】:
谢谢,我什至没有考虑元组。这是我对第三种选择的主要问题:我觉得它并不能真正保证一个全新的课程。 +1 也适用于元组,这可能是我最喜欢的 .NET 4 之一。 数不清这些年来我创建了多少自定义元组类 - 很高兴终于有了一个真正的元组!现在,如果我只能让我们的项目从 3.4 更新到 4... 伙计,我想要元组。 :( 以前从未使用过,但它看起来很有用。【参考方案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
感觉干净多了。
【讨论】:
我认为这是最后一个选项......虽然我个人认为它是不可变的。 @Jon:是的,这是最后一个选项,当然它应该是不可变的。我不知道我怎么了;今天不应该在这里;)【参考方案3】:我更喜欢最后一个选项。 Out 参数很少使用,可能会让一些人感到惊讶/困惑。创建复合结果对象是一个干净的解决方案。唯一的缺点是您必须专门为此目的创建一个类。
【讨论】:
".. 很少使用,可能会令人惊讶.." - 尝试告诉 C 或 C++ 程序员!【参考方案4】:我会说第三个,因为它将您需要的逻辑封装在一个位置。我只能假设 SftpResult 和 ArrayList 返回方法应该是私有的,然后组成复合返回对象的内部逻辑。
【讨论】:
【参考方案5】:我会成功的:
public static bool GetFileList(string directory, out SftpResult result, out ArrayList fileNames)
所以对于函数的作用没有混淆,如果 GetFileList 失败,我也会返回一个布尔值。
【讨论】:
【参考方案6】:如果你喜欢一个函数做两件事的设计,那么我会使用一个 la Jon 的元组或一个 la Fredrik 的返回对象。
如果您想完全了解它,您可以让类型系统完成工作:
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】:为什么不提供全部三个?我更喜欢在我的函数调用中没有参数,但我可以理解很多时候需要它们。如果您不知道要支持哪个签名,则支持所有三个。最终,选择权在呼叫者一方,您能做的最好的事情就是提供这个选择。
【讨论】:
以上是关于返回码还是输出参数?的主要内容,如果未能解决你的问题,请参考以下文章