为什么.NET中的'out'参数不是一个好主意?
为什么.NET中的'out'参数是个坏主意?
最近有人问我这个问题,但是除了它不必要地使应用程序复杂化之外,我没有真正的答案。还有什么其他原因?
解决方案
我会说我们给出的答案是关于最好的答案。如果可能的话,我们应该始终避免使用out参数,因为这通常会使代码变得不必要地复杂。
但这几乎适用于任何模式。如果不需要它,请不要使用它。
我不认为这是真正的原因,尽管我没有看到它经常使用(除了P / Invoke调用之外)。
好吧,我认为它们不是一个坏主意。 Dictionary <K,V>有一个TryGetValue方法,这是一个很好的例子,为什么out参数有时是一件很不错的事情。
我们当然不应过度使用此功能,但是每个定义都不是一个坏主意。尤其是不在Cwhere中,我们必须在函数声明和调用中记下out
关键字,这使正在发生的事情显而易见。
out关键字是必需的(请参见SortedDictionart.TryGetValue
)。它暗示通过引用传递,并且还告诉编译器以下内容:
int value; some_function (out value);
是可以的,并且" some_function"没有使用统一的值,这通常是错误的。
他们是一个好主意。因为有时我们只想从一个方法返回多个变量,而又不想为此创建"繁重的"类结构。包装类结构可以隐藏信息流动的方式。
我用它来:
- 一次通话即可返回密钥和IV数据
- 将人名拆分为不同的实体(名字,中间名和姓氏)
- 分割地址
我想说的是答案是正确的;通常这是不必要的并发症,而且通常设计更简单。在.NET中使用的大多数方法都不会改变其输入参数,因此,采用一种一次性使用该语法的方法会造成一些混乱。代码变得不太直观,并且在方法文献记录不充分的情况下,我们无法知道该方法对输入参数的作用。
此外,如果我们关心的是没有参数的方法签名,则会触发代码分析/ FxCop违规。在大多数情况下,有一种更好的方法可以实现使用" out"参数的方法的意图,并且可以重构该方法以返回有趣的信息。
我不认为他们是。滥用它们不是一个好主意,但这适用于任何编码实践/技术。
我认为在某些情况下,这是一个好主意,因为它们允许从一个函数中返回多个对象,例如:
DateTime NewDate = new DateTime(); if (DateTime.TryParse(UserInput, out NewDate) == false) { NewDate = DateTime.Now; }
很有用 :)
使用参数并不总是一个坏主意。通常,对于尝试基于某种形式的输入创建对象的代码,最好提供一个带参数和布尔返回值的Try方法,而不是强迫方法使用者将try catch块全部包装起来,更不用说更好的性能。
例子:
bool TryGetSomeValue(out SomeValue value, [...]);
在这种情况下,out参数是一个很好的想法。
另一种情况是我们要避免在方法之间传递昂贵的大型结构。
例如:
void CreateNullProjectionMatrix(out Matrix matrix);
此版本避免了昂贵的结构复制。
但是,除非出于特定原因需要退出,否则应避免这种情况。
我必须同意GateKiller。我无法想象,如果Microsoft将它们用作基础库的一部分,那么参数就太糟糕了。但是,与所有事物一样,最好适度。
就像Tanqueray的人喜欢适度地说"一切"。
我绝对会强调不要过度使用,因为它会导致"用c#编写c"与人们用Python编写Java的方式几乎相同(在这里,我们不接受使新语言特别的模式和习惯用法,而是只需用旧语言思考并转换为新语法)。还是一如既往地,如果它可以帮助代码更优雅,更有意义,那么请继续努力。
.NET以外的某些语言将它们用作无作用宏,这些宏仅向程序员提供有关函数中如何使用参数的信息。
我没有提到的一点是,out关键字还要求调用者指定out。这很重要,因为它有助于确保调用者了解调用此函数将修改其变量。
这就是为什么我从不喜欢在C ++中将引用用作out参数的原因之一。调用者可以轻松地调用方法,而无需知道其参数将被修改。
我认为Out Parameter是个坏主意。它们增加了副作用的风险,并且难以调试。唯一好的解决方案是函数结果,这就是问题所在:对于函数结果,必须为每个复杂结果创建一个元组或者新类型。现在,在c#中使用匿名类型和泛型应该相当容易。
顺便说一句:我也讨厌副作用。
好吧,目前还没有明确的答案,但是out参数的简单用例是" Int.TryParse(" 1",out myInt)"
XXX.TrayParse方法作业是将某种类型的值转换为另一种类型,它会向我们返回一个布尔值标志以指示转换成功或者失败,这是一部分,另一部分是转换后的值,该值被携带通过该方法中的out参数。
.NET 2.0中引入了此TryParse方法,以克服以下事实:如果转换失败,则XXX.Parse将通过异常,因此我们必须在语句周围放入try / catch。
因此,基本上,这取决于方法在做什么,以及调用者期望的方法是什么,如果我们正在执行的方法返回某种形式的响应代码,则可以使用out参数来执行方法返回的结果。
无论如何,微软在其设计指南中说"避免使用参数",请检查此msdn页
http://msdn.microsoft.com/zh-CN/library/ms182131(VS.80).aspx
'out`'很棒!
它明确声明该参数包含该方法要返回的值。
编译器还会强制我们对其进行初始化(如果我们将其用作返回参数,则应对其进行初始化)。
问题的措词是"你停止打妻子了吗?"综上所述,假设out参数不一定是个坏主意。在某些情况下,可能会滥用out参数,但是
- 它们实际上非常适合C#语言。它们类似于ref参数,只是保证方法可以为其分配值,并且调用方无需初始化变量。
- 函数的正常返回值被压入堆栈,并在其中调用和退出它们。提供out参数时,将为该方法提供特定的内存地址以将结果保留在其中。这也允许多个返回值,尽管使用结构通常更有意义。
- 它们对于TryParse模式非常有用,并且还为其他事情提供元数据,例如在SQL-CLR情况下,其中out参数映射到存储过程签名的out参数。