2011-10-15 34 views
16

我鄙视出来的和裁判的作为方法参数。恕我直言,他们使代码不那么干净,并提供副作用的机会。但我承认我可能不了解他们的用处,这可能解释我的一部分厌恶。请问,有人可以解释一个有效的情况出来或参考?在方法中使用“out”或“ref”参数的正当理由是什么?

+0

你在问这两者之间的区别,或者一般使用它们的目的是什么?为什么这个标记为java? – Marlon

+2

你认为他们如何提供机会对于副作用? – svick

+0

http://stackoverflow.com/questions/635915/when-to-use-ref-and-when-it-is-not-necessary-in-c-sharp –

回答

18

基本上,如果你需要返回多个值,它是使用类似Tuple<,>或自定义类型封装值的替代品。规范示例可能是int.TryParse及相关方法。他们想要传达两个信息回:

  • 分析得到的值
  • 无论解析成功。

现在,这些可能实际上已经在这种情况下使用的int?等返回类型编写的,但它是其他情况相同的原则。 (例如,Dictionary<,>.TryGetValue,其中存储在字典中的值可以合法地为空)。

我不会说我鄙视outref参数,但我相信他们应该只偶尔使用,并且只当没有更好的选择。我在堆栈溢出中看到的大多数ref的用法都是由于误解了参数传递。

+0

'ref'用法的好例子是什么? –

+0

@SaeedAmiri:大致相同,但您希望变量也可用作输入。这有点像有一个“in”参数和另一个“out”参数,除了调用者不能分开这两个参数:) –

+1

对不起一个问题,为什么.net团队决定在tryparse中使用'out'而不是'ref'? –

6

out提供了一种方法返回多个值。 ref是相同的,但您可以传中的值。

注意,您可以发生变异,即使没有ref声明的对象(假设它是在第一时间当然是可变的)。

我宁愿out另一种方法是使一个类来包含所有返回值,并返回类的一个实例。

+0

不止一个,而不仅仅是两个。 –

+1

“out”参数肯定会为副作用提供机会 - 它们要求该方法要么永远运行,要么异常终止,要么变异变量*。这是一个副作用。 –

1

它们几乎相同 - 唯一的区别是您作为out参数传递的变量不需要初始化,并且使用参数out的方法必须将其设置为某个值。

int x; 
Foo(out x); 

int y; 
Foo(ref y); 

Ref参数是可能被修改的数据,out参数是这对功能的额外输出已经在使用的东西的返回值数据(例如int.TryParse)。

+1

这是真的吗?参考文献未初始化时会得到什么错误? –

+0

另外OP要求在.net中使用它(通过知道可用的替代方法)而不是它们的区别, –

+2

@AshBurlaczenko:它当然是真的,如果你想知道你得到了什么错误,请启动编译器并找出。 –

5

“新”(C#4.0)lock使用ref(技术上lock语句是新的Monitor.Enter过载的语法糖)。这是不可能做到这一点,而不:-)

bool acquiredLock = false; 

try 
{ 
    Monitor.Enter(lockObject, ref acquiredLock); 

    // Code that accesses resources that are protected by the lock. 

} 
finally 
{ 
    if (acquiredLock) 
    { 
     Monitor.Exit(lockObject); 
    } 
} 

所以在非常关键的地方ref空间。

为什么简单地返回一个布尔值是不够的原因是一个例外可以在Monitor.Enterreturn truebool acquiredLock =之间的一个问题:“离开你的程序锁tacken发生?“ref参数解决了这个问题

+0

+1我正在寻找好的参考样本 –

+0

但是,为什么不'var acquiredLock = Monitor.Enter(lockObject)'?尽管使用了'ref',我拒绝这是'*好需要*'。可以说标准的'Dictionary.TryGetValue'是一个更好的例子,因为它有两个必须返回的值(key found和value)。 – 2011-10-15 20:14:50

+0

@pst:再次阅读最后一段。您不能*返回*锁是否被采用,因为当返回值被放到“堆栈”和返回值被复制到变量中时,*之间可能会有一个异常*。 –

相关问题