日期:2014-05-18  浏览次数:20941 次

关于引用类型作为参数加上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 6