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

我有一个对象,它是程序的内存状态,还有一些其他的工作函数,我传递这个对象来修改状态。我已经通过引用将它传递给 worker 函数。但是我遇到了以下函数。

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);

这让我很困惑,因为 received_sremoteEP都在从函数返回东西。为什么 remoteEP需要 refreceived_s不需要?

我也是一个 c 程序员,所以我有一个问题得到指针了我的头。

编辑: 看起来 C # 中的对象是指向引擎盖下的对象的指针。所以当你把一个对象传递给一个函数时,你可以通过指针来修改对象的内容,而传递给函数的唯一东西就是指向对象的指针,这样对象本身就不会被复制。如果希望能够在函数中切换或创建一个类似于双指针的新对象,可以使用 ref 或 out。

90056 次浏览

因为 interface _ s 是一个数组,所以要传递一个指向该数组的指针。该函数在适当的位置操作现有数据,而不更改基础位置或指针。Ref 关键字表示您正在传递指向位置的实际指针并更新外部函数中的指针,因此外部函数中的值将发生变化。

例如,字节数组是一个指向相同内存的指针之前和之后,内存刚刚被更新。

Endpoint 引用实际上是将外部函数中的 Endpoint 指针更新为函数内生成的新实例。

简短的回答: 读我的 关于传递参数的文章

长答案: 当引用类型参数通过值传递时,只传递引用,没有是对象的副本。这就像在 C 或 C + + 中传递一个指针(通过值)。调用者不会看到参数本身值的更改,但是可以看到引用指向 威尔的对象的更改。

当一个参数(任何类型)被传递给 作者引用时,这意味着对参数的任何更改都会被调用者看到——参数 对变量的更改。

当然,本文将更详细地解释这一切:)

Useful answer: 几乎不需要使用 ref/out. It's basically a way of getting another return value, and should usually be avoided precisely because it means the method's probably trying to do too much. That's not always the case (TryParse etc are the canonical examples of reasonable use of out) but using ref/out should be a relative rarity.

可以将 ref 看作是通过引用传递指针的意思。不使用 ref 意味着通过值传递指针。

更好的方法是,忽略我刚才说的内容(这可能会误导,特别是对于值类型) ,阅读 这个 MSDN 页面

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

几乎不应该通过 ref 传递值。我怀疑如果不是出于互操作的考虑。网络团队永远不会将其包括在原始规范中。面向对象处理 ref 参数解决的大多数问题的方法是:

For multiple return values

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

对于由于方法调用 而在方法中发生变化的原语(方法对原语参数有副作用)

  • 将对象中的方法实现为实例方法,并将对象的状态(而不是参数)作为方法调用的一部分进行操作
  • Use the multiple return value solution and merge the return values to your state
  • 创建一个包含可由方法操作的状态的对象,并将该对象作为参数传递,而不是原语本身。

您可能会编写一个完整的 C # 应用程序,而且永远不会通过 ref 传递任何对象/结构。

有个教授告诉我:

使用参考文献的唯一地方是:

  1. 希望传递一个大型对象(即,对象/结构具有 内部的对象/结构到多个级别) ,并复制它 价格昂贵
  2. You are calling a Framework, Windows API or other API that requires 它。

Don't do it just because you can. You can get bit in the ass by some 如果您开始更改参数中的值,并且没有更改,则会出现讨厌的 bug 集中注意力。

I agree with his advice, and in my five plus years since school, I've never had a need for it outside of calling the Framework or Windows API.

我的理解是,从 Object 类派生的所有对象都作为指针传递,而普通类型(int、 struct)不作为指针传递,需要 ref。我对字符串也不确定(它最终是从 Object 类派生出来的吗?)

基本原则优先,在涉及 TYPES 的上下文中,通过值(堆栈)传递基本原则,通过引用(堆)传递非基本原则。

默认情况下,Value 传递所涉及的参数。 好帖子,详细解释事情。 Http://yoda.arachsys.com/csharp/parameters.html

Student myStudent = new Student {Name="A",RollNo=1};


ChangeName(myStudent);


static void ChangeName(Student s1)
{
s1.Name = "Z"; // myStudent.Name will also change from A to Z
// {AS s1 and myStudent both refers to same Heap(Memory)
//Student being the non-Primitive type
}


ChangeNameVersion2(ref myStudent);
static void ChangeNameVersion2(ref Student s1)
{
s1.Name = "Z"; // Not any difference {same as **ChangeName**}
}


static void ChangeNameVersion3(ref Student s1)
{
s1 = new Student{Name="Champ"};


// reference(myStudent) will also point toward this new Object having new memory
// previous mystudent memory will be released as it is not pointed by any object
}

我们可以说(带有警告)非原语类型只不过是 < strong > Pointers 当我们通过裁判传球的时候,我们可以说我们传了 < strong > Double Pointer

虽然我总体上同意 Jon Skeet 的答案和其他一些答案,但是使用 ref有一个用例,那就是加强性能优化。在性能分析期间已经观察到,设置方法的返回值对性能有轻微的影响,而使用 ref作为参数,返回值被填充到该参数中会导致消除这个轻微的瓶颈。

这只有在优化工作达到极端水平、牺牲可读性、可测试性和可维护性以节省毫秒或分毫秒的情况下才真正有用。