ref与out的区别(反汇编篇)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace refout
{
class Program
{
static void Main(string[] args)
{
testParams tp = new testParams();
Int32 x = 23;
Int32 y = 45;
Console.WriteLine("x={0},y={1}",x,y);
tp.changeWithoutRef(x,y);
Console.WriteLine("没加ref的change之后:");
Console.WriteLine("x={0},y={1}", x, y);
tp.changeWithRef(ref x,ref y);
Console.WriteLine("加ref的change之后:");
Console.WriteLine("x={0},y={1}", x, y);
Console.ReadKey();
}
}
public class testParams{
public void changeWithoutRef(Int32 a,Int32 b){//此处取断点
Int32 temp;
temp = a;
a = b;
b = temp;
}
public void changeWithRef(ref Int32 a,ref Int32 b) {//此处取断点
Int32 temp=0;
temp = a;
a = b;
b = temp;
}
}
}
运行后,程序断下,按调试-->窗口-->反汇编进入相应方法的反汇编窗口,我们会看到:
对于方法 changeWithoutRef
--- d:\用户目录\documents\visual studio 2010\Projects\refout\refout\Program.cs -----
public void changeWithoutRef(Int32 a,Int32 b){
00000000 push ebp
00000001 mov ebp,esp
00000003 push edi
00000004 push esi
00000005 push ebx
00000006 sub esp,38h
00000009 mov esi,ecx
0000000b lea edi,[ebp-38h]
0000000e mov ecx,0Bh
00000013 xor eax,eax
00000015 rep stos dword ptr es:[edi]
00000017 mov ecx,esi
00000019 xor eax,eax
0000001b mov dword ptr [ebp-1Ch],eax
0000001e mov dword ptr [ebp-3Ch],ecx
00000021 mov dword ptr [ebp-40h],edx
00000024 cmp dword ptr ds:[00249284h],0
0000002b je 00000032
0000002d call 6EA2EBA9
00000032 xor edx,edx
00000034 mov dword ptr [ebp-44h],edx
00000037 nop
Int32 temp;
temp = a;
00000038 mov eax,dword ptr [ebp-40h]
0000003b mov dword ptr [ebp-44h],eax //直接将eax的值进行传递
a = b;
0000003e mov eax,dword ptr [ebp+8]
00000041 mov dword ptr [ebp-40h],eax
b = temp;
00000044 mov eax,dword ptr [ebp-44h]
00000047 mov dword ptr [ebp+8],eax
}
0000004a nop
0000004b lea esp,[ebp-0Ch]
0000004e pop ebx
0000004f pop esi
00000050 pop edi
00000051 pop ebp
00000052 ret 4
而对于方法changeWithRef
--- d:\用户目录\documents\visual studio 2010\Projects\refout\refout\Program.cs -----
public void changeWithRef(ref Int32 a,ref Int32 b) {
00000000 push ebp
00000001 mov ebp,esp
00000003 push edi
00000004 push esi
00000005 push ebx
00000006 sub esp,38h
00000009 mov esi,ecx
0000000b lea edi,[ebp-38h]
0000000e mov ecx,0Bh
00000013 xor eax,eax
00000015 rep stos dword ptr es:[edi]
00000017 mov ecx,esi
00000019 xor eax,eax
0000001b mov dword ptr [ebp-1Ch],eax
0000001e mov dword ptr [ebp-3Ch],ecx
00000021 mov dword ptr [ebp-40h],edx
00000024 cmp dword ptr ds:[00239284h],0
0000002b je 00000032
0000002d call 6E92EB41
00000032 xor edx,edx
00000034 mov dword ptr [ebp-44h],edx
00000037 nop
Int32 temp=0;
00000038 xor edx,edx
0000003a mov dword ptr [ebp-44h],edx
temp = a;
0000003d mov eax,dword ptr [ebp-40h]
00000040 mov eax,dword ptr [eax] //取得eax的地址
00000042 mov dword ptr [ebp-44h],eax //再将eax的值进行传递,注意此时的eax已经成为原值的地址
a = b;
00000045 mov eax,dword ptr [ebp+8]
00000048 mov eax,dword ptr [eax]
0000004a mov edx,dword ptr [ebp-40h]
0000004d mov dword ptr [edx],eax
b = temp;
0000004f mov eax,dword ptr [ebp+8]
00000052 mov edx,dword ptr [ebp-44h]
00000055 mov dword ptr [eax],edx
}
00000057 nop
00000058 lea esp,[ebp-0Ch]
0000005b pop ebx
0000005c pop esi
0000005d pop edi
0000005e pop ebp
0000005f ret 4
结论:无论值类型还是引用类型,不加ref就是传值,加了ref就是传地址