C#中的ref/out参数与惰性

3
我有一个方法,其中有几个“out”参数。它们是“out”的,因为函数内部应该将值设置给它们。但在某些情况下,编译器并不聪明,它看不到参数值在任何执行路径中都被设置。这就是为什么我不得不在方法开始时为输出参数设置默认值。但由于这个方法是接口的一部分,有几个实现,这个初始化代码是重复的。而且我不喜欢这样。
你看到了解决这个问题的哪些选项?我看到的一个选择是使用ref而不是out。从概念上讲,这并不正确,因为它不能保证参数值在方法内被设置。但实际上它是一样的(因为我在函数开头设置了默认值,这意味着在这种情况下,out不能保证真正的值在方法内被设置)。
还有其他选项吗?

你能给我们展示一个“编译器不够聪明”的例子吗? - LukeH
是的,我从来没有见过编译器无法推断出分配的情况。 - Matt H
3
private void Foo(out int bar) { int[] blah = { 1 }; foreach (var item in blah) { bar = 5; } }这段代码中,变量bar始终会被赋值,尽管编译器没有检测出来。请注意,不要改变原来的意思。 - Adam Robinson
@LukeH:巧合的是,你的问题(即“编译器何时不够聪明,理论上它可以有多聪明?”)将成为我周四博客的主题。 - Eric Lippert
@Adam:我知道编写能够超越编译器流分析的代码相对容易;我希望OP能够向我们展示一个具体的例子,说明它在他们那里失败了,这样我们就可以建议替代模式。@Eric:期待着。 - LukeH
2个回答

13

个人而言,我尽量避免创建具有“多个”refout参数的方法。

一旦您创建了一个具有不止一个refout参数的方法,个人而言,我认为是时候考虑重构以返回包含所有数据的自定义类型(classstruct根据上下文)了。这有许多优点,特别是因为它允许该类型处理其自身的验证以确保构造正确。

如果您有“多个实现”,那么这尤其正确——因为这样应该极大地减少错误的可能性,并消除大部分重复的代码(因为它可以放在新类型中)。


10

首先,任何具有多个输出参数的方法都是一个设计上的问题。老实说,您真的需要将它们作为单独的参数而不是一个封装良好的返回值吗?只有在这些值无关联的情况下才会是这样...那么也许您的方法一开始就做得太多了。

在框架中,我几乎只在TryParse方法中遇到out参数 - 如果当时已经有Tuple<T1,T2>可用,那么我推测应该会首选使用它。或者,可以使用ParseResult<T>结构。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接