何时使用ref以及在C#中何时不需要

Rex*_*gan 100 c# ref

我有一个对象是我在程序的内存状态,还有一些其他的工作函数,我传递对象来修改状态.我已经通过ref传递给工人函数了.但是我遇到了以下功能.

byte[] received_s = new byte[2048];
IPEndPoint tmpIpEndPoint = new IPEndPoint(IPAddress.Any, UdpPort_msg);
EndPoint remoteEP = (tmpIpEndPoint);

int sz = soUdp_msg.ReceiveFrom(received_s, ref remoteEP); 
Run Code Online (Sandbox Code Playgroud)

它混淆了我,因为两者received_sremoteEP从函数返回的东西.为什么remoteEP需要一个refreceived_s不是一个?

我也是程序员,所以我有一个问题,我的头脑中有指针.

编辑:看起来C#中的对象是引导下对象的指针.因此,当您将对象传递给函数时,您可以通过指针修改对象内容,传递给函数的唯一内容是指向对象的指针,因此对象本身不会被复制.如果您希望能够在函数中切换或创建一个新对象,就像双指针一样,则使用ref或out.

Jon*_*eet 207

简短的回答:阅读关于论证传递的文章.

答案很长:当通过值传递引用类型参数时,只传递引用,而不是对象的副本.这就像在C或C++中传递指针(按值).调用者不会看到对参数本身值的更改,但看到参考指向的对象的更改.

通过引用传递参数(任何类型)时,这意味着调用者可以看到对参数的任何更改 - 对参数更改是对变量的更改.

文章更详细地解释了所有这些,当然:)

有用的答案:你几乎不需要使用ref/out.它基本上是一种获得另一个返回值的方法,通常应该被准确地避免,因为这意味着该方法可能试图做太多.情况并非总是如此(TryParse等等是合理使用的规范示例out)但使用ref/out应该是相对罕见的.

  • 我觉得你得到了简短的回答和长时间的回答; 这是一篇很棒的文章! (32认同)
  • 参考!:) (24认同)
  • @Outlaw:是的,但简短的答案本身,阅读文章的指令,只有6个字长:) (21认同)
  • @Liam像你一样使用ref可能会让你看得更清楚,但它实际上可能让其他程序员感到困惑(那些知道该关键字干扰的人),因为你实际上是在告诉潜在的调用者,"我可以修改**你在调用方法中使用的变量**,即**将它重新分配给另一个对象(如果可能的话,甚至是null)**所以不要挂在它上面,或者确保在我完成时验证它用它".这非常强大,与"可以修改此对象"完全不同,只要将对象引用作为参数传递,*总是*. (5认同)
  • 好文章,乔恩. (3认同)
  • @M.Mimpen:C# 7 将(希望)允许 `if (int.TryParse(text, out int value)) { ... 在这里使用值 ... }` (2认同)

Mic*_*ows 26

可以将非ref参数视为指针,将ref参数视为双指针.这对我帮助最大.

您几乎不应该通过ref传递值.我怀疑,如果不是互操作问题,.Net团队永远不会将其包含在原始规范中.处理ref参数解决的大多数问题的OO方法是:

对于多个返回值

  • 创建表示多个返回值的结构

对于作为方法调用结果在方法中更改的基元(方法对基本参数有副作用)

  • 在对象中实现方法作为实例方法,并在方法调用中操纵对象的状态(而不是参数)
  • 使用多重返回值解决方案并将返回值合并到您的状态
  • 创建一个包含可由方法操作的状态的对象,并将该对象作为参数传递,而不是基元本身.

  • 天哪.我必须阅读这20倍才能理解它.听起来像是一堆额外的工作,只是为了做一些简单的事情. (8认同)

Chr*_*ris 9

您可以编写一个完整的C#应用​​程序,并且不会通过ref传递任何对象/结构.

我有一位教授告诉我这件事:

您使用refs的唯一地方是:

  1. 想要传递一个大对象(即,对象/结构中有对象/结构到多个级别)并且复制它会很昂贵,
  2. 您正在调用Framework,Windows API或其他需要它的API.

不要因为你能做到这一点.如果您开始更改参数中的值并且没有引起注意,您可以通过一些令人讨厌的错误获得帮助.

我同意他的建议,在学校开始的五年多时间里,除了调用Framework或Windows API之外,我从未需要它.

  • 如果您计划实现“交换”,则通过ref传递可能会有所帮助。 (2认同)
  • @Chris - 我很确定传递一个“大”物体并不昂贵。如果您只是按值传递它,那么您仍然只是传递一个指针,对吗? (2认同)