返回码还是输出参数?

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)

(其中SftpFileListResultSftpResultArrayList 的复合对象)

哪个是首选,为什么?

【问题讨论】:

SftpResult 的目的是什么?如果它应该解释调用失败的原因,也许你应该抛出一个异常。 考虑到我所做的只是报告状态,我认为这太过分了。如果它失败,这不是一个严重的问题,而且我真的不需要仅仅因为他们输入了错误的目录而展开堆栈。我只是返回一个 DirectoryNotFound 并继续我的业务 :-) 考虑放弃使用 ArrayList 转而使用 IEnumerable 谢谢 Eric,我现在正在尝试这样做。有没有更短的写法:return 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】:

为什么不提供全部三个?我更喜欢在我的函数调用中没有参数,但我可以理解很多时候需要它们。如果您不知道要支持哪个签名,则支持所有三个。最终,选择权在呼叫者一方,您能做的最好的事情就是提供这个选择。

【讨论】:

以上是关于返回码还是输出参数?的主要内容,如果未能解决你的问题,请参考以下文章

为啥使用 Bash 只读变量捕获输出无法捕获返回码 $?

PHP获取小程序码并返回前端显示图片

javascript如何验证session中的验证码?

welink返回错误码-11

浏览器中返回的状态码400是啥?

返回码:1 输出:Dockerfile 和 Dockerrun.aws.json 都丢失,中止部署