主题:关于引用类型作为参数加上ref与不加ref的区别
众所周知,引用有class,object,string,delegate,,interface。
按道理说引用类型作为参数的时候是引用传递值的。最近写程序的时候无意中发现 引用类型 作为参数的时候,加上ref 与不加ref是有区别的。
以下以class类型 作为测试:
测试代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
public class Test
{
private string _message;
public string Message
{
get
{
return _message;
}
set
{
_message = value;
}
}
}
class Program
{
static void Main(string[] args)
{
Test a = new Test();
a.Message = "初始值";
Test001(a);
Console.WriteLine("没有添加ref关键字,也没有对引用参数引用了新的一个Test类型的对象,结果为:{0}",a.Message);
Test b = new Test();
b.Message = "初始值";
TestRef(b);
Console.WriteLine("没有添加ref关键字,并重新对引用参数引用了新的一个Test类型的对象,结果为:{0}", b.Message);
Test c = new Test();
c.Message = "初始值";
TestRef(ref c);
Console.WriteLine("关键字ref关键字,并重新对引用参数引用了新的一个Test类型的对象,结果为:{0}", c.Message);
Console.Read();
}
static void TestRef(Test t)
{
t = new Test();
t.Message = "对象已赋值";
}
static void TestRef(ref Test t)
{
t = new Test();
t.Message = "对象已赋值";
}
static void Test001(Test t)
{
t.Message = "对象已赋值";
}
}
}
给出每个方法的IL
TestRef(Test t)
.method private hidebysig static void TestRef(class ConsoleApplication1.Test t) cil managed
{
// 代码大小 21 (0x15)
.maxstack 8
IL_0000: nop
IL_0001: newobj instance void ConsoleApplication1.Test::.ctor()
IL_0006: starg.s t
IL_0008: ldarg.0
IL_0009: ldstr bytearray (F9 5B 61 8C F2 5D 4B 8D 3C 50 ) // .[a..]K.<P
IL_000e: callvirt instance void ConsoleApplication1.Test::set_Message(string)
IL_0013: nop
IL_0014: ret
} // end of method Program::TestRef
TestRef(ref Test t)
.method private hidebysig static void TestRef(class ConsoleApplication1.Test& t) cil managed
{
// 代码大小 22 (0x16)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: newobj instance void ConsoleApplication1.Test::.ctor()
IL_0007: stind.ref
IL_0008: ldarg.0
IL_0009: ldind.ref
IL_000a: ldstr bytearray (F9 5B 61 8C F2 5D 4B 8D 3C 50 ) // .[a..]K.<P
IL_000f: callvirt instance void ConsoleApplication1.Test::set_Message(string)
IL_0014: nop
IL_0015: ret
} // end of method Program::TestRef
Test001(Test t)
.method private hidebysig static void Test001(class ConsoleApplication1.Test t) cil managed
{
// 代码大小 14 (0xe)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldstr bytearray (F9 5B 61 8C F2 5D 4B 8D 3C 50 ) // .[a..]K.<P
IL_0007: callvirt instance void ConsoleApplication1.Test::set_Message(string)
IL_000c: nop
IL_000d: ret
} // end of method Program::Test001
按道理说引用类型作为参数的时候是引用传递值的。最近写程序的时候无意中发现 引用类型 作为参数的时候,加上ref 与不加ref是有区别的。
以下以class类型 作为测试:
测试代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
public class Test
{
private string _message;
public string Message
{
get
{
return _message;
}
set
{
_message = value;
}
}
}
class Program
{
static void Main(string[] args)
{
Test a = new Test();
a.Message = "初始值";
Test001(a);
Console.WriteLine("没有添加ref关键字,也没有对引用参数引用了新的一个Test类型的对象,结果为:{0}",a.Message);
Test b = new Test();
b.Message = "初始值";
TestRef(b);
Console.WriteLine("没有添加ref关键字,并重新对引用参数引用了新的一个Test类型的对象,结果为:{0}", b.Message);
Test c = new Test();
c.Message = "初始值";
TestRef(ref c);
Console.WriteLine("关键字ref关键字,并重新对引用参数引用了新的一个Test类型的对象,结果为:{0}", c.Message);
Console.Read();
}
static void TestRef(Test t)
{
t = new Test();
t.Message = "对象已赋值";
}
static void TestRef(ref Test t)
{
t = new Test();
t.Message = "对象已赋值";
}
static void Test001(Test t)
{
t.Message = "对象已赋值";
}
}
}
给出每个方法的IL
TestRef(Test t)
.method private hidebysig static void TestRef(class ConsoleApplication1.Test t) cil managed
{
// 代码大小 21 (0x15)
.maxstack 8
IL_0000: nop
IL_0001: newobj instance void ConsoleApplication1.Test::.ctor()
IL_0006: starg.s t
IL_0008: ldarg.0
IL_0009: ldstr bytearray (F9 5B 61 8C F2 5D 4B 8D 3C 50 ) // .[a..]K.<P
IL_000e: callvirt instance void ConsoleApplication1.Test::set_Message(string)
IL_0013: nop
IL_0014: ret
} // end of method Program::TestRef
TestRef(ref Test t)
.method private hidebysig static void TestRef(class ConsoleApplication1.Test& t) cil managed
{
// 代码大小 22 (0x16)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: newobj instance void ConsoleApplication1.Test::.ctor()
IL_0007: stind.ref
IL_0008: ldarg.0
IL_0009: ldind.ref
IL_000a: ldstr bytearray (F9 5B 61 8C F2 5D 4B 8D 3C 50 ) // .[a..]K.<P
IL_000f: callvirt instance void ConsoleApplication1.Test::set_Message(string)
IL_0014: nop
IL_0015: ret
} // end of method Program::TestRef
Test001(Test t)
.method private hidebysig static void Test001(class ConsoleApplication1.Test t) cil managed
{
// 代码大小 14 (0xe)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldstr bytearray (F9 5B 61 8C F2 5D 4B 8D 3C 50 ) // .[a..]K.<P
IL_0007: callvirt instance void ConsoleApplication1.Test::set_Message(string)
IL_000c: nop
IL_000d: ret
} // end of method Program::Test001