使用ref关键字传递值

时间:2013-12-12 19:17:36

标签: c# parameters ref

在阅读the MSDN article on the ref keyword之后,我对使用ref关键字传递值类型时C#的作用感到困惑。文档指出ValueTypes没有装箱。我的问题是C#如何处理传递值类型作为引用?它是否将一些副本传递给堆栈上分配的数据?谢谢。

2 个答案:

答案 0 :(得分:8)

  

是否将一些副本传递给堆栈上分配的数据?

不,它不会复制。当传递内存位置(即地址)时,refout关键字可以与通过C中的指针传递或通过C ++中的引用传递进行比较目标方法。然后,接受引用的方法将使用传入的内存位置直接修改该值。

知道变量是通过引用传递的,编译器会插入将ref变量视为地址的指令,允许就地修改。

答案 1 :(得分:0)

tl;博士:拳击不是“你如何创建参考”;它是“如何为不期望精确类型的消费者打包原始值类型”。

在.NET中,引用类型是堆上的类实例。像intdouble这样的值类型只是字节:32位int只有4个字节的零和1。当你把它放入时,比如说System.List(Granpaw在General Store中缩减的旧式预先通用类型),然后将其取回,编译器如何知道如果你做什么在上面调用GetType()?它只有四个字节......什么?谁知道?如果它在List中存储了一个指针,它会有一个指针到四个字节......谁知道?

在您自己的方法中,生成的代码知道您的变量是什么。定期强大的类型检查。但是,当您将变量的值发送给只知道他期望Object的其他人时,这不起作用。

因此,当您向int添加List或将其传递给以Object作为参数的函数时,编译器必须向其中添加一些信息,以便其他人知道他得到了什么。

所以“Boxing”意味着将非参考值打包到一个可被视为Object实例的对象中。对于普通的ref参数,这是不必要的,因为类型是全部已知的:为函数的内容生成的代码不必准备好处理任何任意引用类型。它知道它正在获取(例如)一个指向整数的指针,而这就是它将要获得的全部内容。 Boxing提供了在这种情况下不需要的功能,因此编译器不会浪费用户的周期。

拳击不是唯一的方式,例如,double有一个参考(在最广泛的意义上)。相反,装箱是将double视为可以存储在System.List中的对象的唯一方法:它必须在堆上,它必须可以转换为Object,必须有运行时类型信息等。

对于以下内容,所有调用者或被调用者需要的是64 zeroes and ones某处的地址:

void f(ref double d) { d *= 2; }