输出参数有什么问题?

在SQL和C#中,我从来都不喜欢输出参数。 我从未在VB6中传递参数ByRef。 关于计算副作用以完成某些事情的事情让我感到困扰。

我知道它们是一种无法从函数返回多个结果的方法,但SQL中的行集或C#和VB中的复杂数据类型也同样适用,并且对我来说似乎更自我记录。

我的想法有什么问题,还是来自权威来源的资源支持我? 你个人对此有何看法,为什么? 对于想要设计输出参数可能会说服他们使用不同结构的同事,我能说些什么呢?

编辑:有趣的转 – 输出参数我问这个问题用于代替返回值。 当返回值为“ERROR”时,调用者应该将其作为exception处理。 我这样做但对这个想法并不满意。 一位同事没有被告知有必要处理这种情况,因此,由于程序无声地失败,大量资金丢失了!

Bob Martin写了关于这个清洁代码的文章。 输出参数打破了函数的基本思想。

output = someMethod(input)

输出参数可能是代码气味,表明您的方法做得太多。 如果您需要返回多个值,则该方法可能不止一件事。 如果数据紧密相关,那么它可能会从包含两个值的类中受益。

当然,这并非总是如此,但我发现通常就是这种情况。

换句话说,我认为你应该避免它们。

他们有自己的位置。 Int32.TryParse方法是有效使用out参数的一个很好的例子。

 bool result = Int32.TryParse(value, out number); if (result) { Console.WriteLine("Converted '{0}' to {1}.", value, number); } 

我认为它们对于在同一个SQL命令中获取新插入的行的ID非常有用,但我认为我没有将它们用于其他许多行。

我也看到很少使用out / ref参数,尽管在SQL中有时通过参数传递值比使用结果集更容易(这需要使用DataReader等)

虽然,幸运的是,我今天在C#中创建了一个这样罕见的function。 它validation了一个类似于表的数据结构,并返回了它中的行数和列数(计算起来很棘手,因为该表可能具有HTML中的rowspans / colspans)。 在这种情况下,两个值的计算同时进行。 将它分成两个函数会导致代码,内存和CPU时间要求翻倍。 只为这一个函数创建一个自定义类型返回对我来说似乎也是一种矫枉过正。

所以 – 有时候它们是最好的东西,但大多数情况下,如果没有它们,你可以做得很好。

SQL Server 2005及更高版本中的OUTPUT子句是获取受DML语句影响的行的任何字段值的重要一步。 我认为有很多情况会消除输出参数。

在VB6中,ByRef参数适合传递ADO对象。

除了我想到的两个具体案例,我倾向于避免使用它们。

仅限SQL …

存储过程输出参数很有用。

  1. 假设您需要一个值。 你是否“创建#table,插入… exec,选择@var =”。 或者使用输出参数?

  2. 对于客户端调用,输出参数比处理记录集要快得多。

  3. 使用RETURN值仅限于有符号整数。

  4. 更容易重复使用(例如安全检查助手程序)

  5. 同时使用:recordsets = data,输出参数= status / messages / rowcount等

  6. 存储过程记录集输出不能像UDF或客户端代码那样强类型化

  7. 您不能总是使用UDF(例如,在上面的安全检查期间记录)

但是,只要您通常不使用相同的参数进行输入和输出,那么在SQL完全更改之前,您的选项将受到限制。 说,我有一个案例,我使用参数进出值,但我有充分的理由。

我的两分钱:
我同意输出参数是一种有关的做法。 VBA通常由编程非常新的人维护,如果维护代码的人没有注意到参数是ByRef,他们可能会引入一些严重的逻辑错误。 它也倾向于破坏Property / Function / Sub范例。
使用out参数的另一个原因是不好的做法是,如果您确实需要返回多个值,那么您可能应该在数据结构中使用这些值,例如类或用户定义类型。
然而,他们可以解决一些问题。 VB5(因此Office 97的VBA)不允许函数返回数组。 这意味着返回或更改数组的任何内容都必须通过“out”参数来完成。 在VB6中已添加此function,但VB6仍然强制数组参数通过引用(以防止在内存中过度复制)。 现在,您可以从更改数组的函数返回值。 但它只是一个慢的头发(由于杂技在幕后进行); 它也可以让新手认为数组输入不会被改变(只有当某人特意以这种方式构建它时才会这样)。 所以我发现如果我有一个改变数组的函数,它可以减少混淆,只使用一个sub而不是一个函数(而且它也会更快一点)。
另一种可能的情况是,如果您要维护代码并且想要在不破坏界面的情况下添加输出值,则可以添加可选的输出参数,并确信您不会破坏任何旧代码。 这不是一个好习惯,但是如果有人想要现在修复的东西,而你没有时间以“正确的方式”进行修改并重新构建一切,这可以成为您工具箱的一个方便的补充。
但是,如果您从头开始开发并且需要返回多个值,则应考虑:
1.打破function。
2.返回UDT。
3.退课。

我一般都不会使用它们,我认为它们很容易混淆,而且容易被滥用。 我们偶尔会使用ref参数,但这更多地与传递结构相关而不是将它们取回。

你的意见听起来很合理。

输出参数的另一个缺点是将结果从一个函数传递到另一个函数所需的额外代码。 您必须声明变量,调用函数以获取其值,然后将值传递给另一个函数。 你不能只是嵌套函数调用。 这使代码读取非常紧迫,而不是声明性地。

C ++ 0x正在获取元组,这是一种类似于匿名结构的东西,其成员可以通过索引访问。 C ++程序员将能够将多个值打包到其中一个并返回它。 C#有这样的东西吗? 也许,它可以返回一个数组吗? 但是,输出参数有点尴尬和不清楚。