Net复习笔记:第二章:IL看引用类型传值和加了ref的引用类型传值的区别

看引用类型传值和加了ref的引用类型传值的区别

(按值传递和按引用传递的IL区别)

1.这种是一般的没有用ref传值的

public partial class hellowordle : System.Web.UI.Page

    {

        protected void Page_Load(object sender, EventArgs e)

        {

            List<prod> stin = new List<prod>();

            stin.Add(new prod() { id = "1", name = "111" });

            stin.Add(new prod() { id = "2", name = "111" });

            stin.Add(new prod() { id = "3", name = "111" });

            Myclo(stin);

        }

 

        public void Myclo(List<prod> stin)

        {

            List<prod> stin1 = new List<prod>();

            stin1.Add(new prod() { id = "7", name = "111" });

            stin1.Add(new prod() { id = "8", name = "111" });

            stin = stin.Concat(stin1).ToList();

        }

    }

    public class prod

    {

        public string id { get; set; }

        public string name { get; set; }

    }

反编译的代码为:

.method public hidebysig instance void  Myclo(class [mscorlib]System.Collections.Generic.List`1<class NetNiBiXiuZhiDao.prod> stin) cil managed

{

  // 代码大小       98 (0x62)

  .maxstack  3

  .locals init ([0] class [mscorlib]System.Collections.Generic.List`1<class NetNiBiXiuZhiDao.prod> stin1,

           [1] class NetNiBiXiuZhiDao.prod '<>g__initLocal3',

           [2] class NetNiBiXiuZhiDao.prod '<>g__initLocal4')

  IL_0000:  nop

  IL_0001:  newobj     instance void class [mscorlib]System.Collections.Generic.List`1<class NetNiBiXiuZhiDao.prod>::.ctor()

  IL_0006:  stloc.0

  IL_0007:  ldloc.0

  IL_0008:  newobj     instance void NetNiBiXiuZhiDao.prod::.ctor()

  IL_000d:  stloc.1

  IL_000e:  ldloc.1

  IL_000f:  ldstr      "7"

  IL_0014:  callvirt   instance void NetNiBiXiuZhiDao.prod::set_id(string)

  IL_0019:  nop

  IL_001a:  ldloc.1

  IL_001b:  ldstr      "111"

  IL_0020:  callvirt   instance void NetNiBiXiuZhiDao.prod::set_name(string)

  IL_0025:  nop

  IL_0026:  ldloc.1

  IL_0027:  callvirt   instance void class [mscorlib]System.Collections.Generic.List`1<class NetNiBiXiuZhiDao.prod>::Add(!0)

  IL_002c:  nop

  IL_002d:  ldloc.0

  IL_002e:  newobj     instance void NetNiBiXiuZhiDao.prod::.ctor()

  IL_0033:  stloc.2

  IL_0034:  ldloc.2

  IL_0035:  ldstr      "8"

  IL_003a:  callvirt   instance void NetNiBiXiuZhiDao.prod::set_id(string)

  IL_003f:  nop

  IL_0040:  ldloc.2

  IL_0041:  ldstr      "111"

  IL_0046:  callvirt   instance void NetNiBiXiuZhiDao.prod::set_name(string)

  IL_004b:  nop

  IL_004c:  ldloc.2

  IL_004d:  callvirt   instance void class [mscorlib]System.Collections.Generic.List`1<class NetNiBiXiuZhiDao.prod>::Add(!0)

  IL_0052:  nop

  IL_0053:  ldarg.1

  IL_0054:  ldloc.0

  IL_0055:  call       class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0> [System.Core]System.Linq.Enumerable::Concat<class NetNiBiXiuZhiDao.prod>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>,

                                                                                                                                                              class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>)

  IL_005a:  call       class [mscorlib]System.Collections.Generic.List`1<!!0> [System.Core]System.Linq.Enumerable::ToList<class NetNiBiXiuZhiDao.prod>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>)

  IL_005f:  starg.s    stin

  IL_0061:  ret

} // end of method hellowordle::Myclo

从代码中我们看以看出

IL_0055:  call       class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0> [System.Core]System.Linq.Enumerable::Concat<class NetNiBiXiuZhiDao.prod>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>,

                                                                                                                                                              class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>)

  IL_005a:  call       class [mscorlib]System.Collections.Generic.List`1<!!0> [System.Core]System.Linq.Enumerable::ToList<class NetNiBiXiuZhiDao.prod>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>)

  IL_005f:  starg.s    stin

在没有用ref传值的时候是执行Concat只是得到了一个新的数组,然后把这个数组通过

(Starg.S)

将位于计算堆栈顶部的值存储在参数槽中的指定索引处。,注意是存储在了

参数槽中,( Myclo(List<prod> stin)的stin的托管堆里面,传过来的是一个拷贝地址)

 

下面是使用了ref的传值:

    public partial class hellowordle : System.Web.UI.Page

    {

        protected void Page_Load(object sender, EventArgs e)

        {

            List<prod> stin = new List<prod>();

            stin.Add(new prod() { id = "1", name = "111" });

            stin.Add(new prod() { id = "2", name = "111" });

            stin.Add(new prod() { id = "3", name = "111" });

            Myclo(ref stin);

        }

 

        public void Myclo(ref List<prod> stin)

        {

            List<prod> stin1 = new List<prod>();

            stin1.Add(new prod() { id = "7", name = "111" });

            stin1.Add(new prod() { id = "8", name = "111" });

            stin = stin.Concat(stin1).ToList();

        }

    }

    public class prod

    {

        public string id { get; set; }

        public string name { get; set; }

    }

 

.method public hidebysig instance void  Myclo(class [mscorlib]System.Collections.Generic.List`1<class NetNiBiXiuZhiDao.prod>& stin) cil managed

{

  // 代码大小       99 (0x63)

  .maxstack  3

  .locals init ([0] class [mscorlib]System.Collections.Generic.List`1<class NetNiBiXiuZhiDao.prod> stin1,

           [1] class NetNiBiXiuZhiDao.prod '<>g__initLocal3',

           [2] class NetNiBiXiuZhiDao.prod '<>g__initLocal4')

  IL_0000:  nop

  IL_0001:  newobj     instance void class [mscorlib]System.Collections.Generic.List`1<class NetNiBiXiuZhiDao.prod>::.ctor()

  IL_0006:  stloc.0

  IL_0007:  ldloc.0

  IL_0008:  newobj     instance void NetNiBiXiuZhiDao.prod::.ctor()

  IL_000d:  stloc.1

  IL_000e:  ldloc.1

  IL_000f:  ldstr      "7"

  IL_0014:  callvirt   instance void NetNiBiXiuZhiDao.prod::set_id(string)

  IL_0019:  nop

  IL_001a:  ldloc.1

  IL_001b:  ldstr      "111"

  IL_0020:  callvirt   instance void NetNiBiXiuZhiDao.prod::set_name(string)

  IL_0025:  nop

  IL_0026:  ldloc.1

  IL_0027:  callvirt   instance void class [mscorlib]System.Collections.Generic.List`1<class NetNiBiXiuZhiDao.prod>::Add(!0)

  IL_002c:  nop

  IL_002d:  ldloc.0

  IL_002e:  newobj     instance void NetNiBiXiuZhiDao.prod::.ctor()

  IL_0033:  stloc.2

  IL_0034:  ldloc.2

  IL_0035:  ldstr      "8"

  IL_003a:  callvirt   instance void NetNiBiXiuZhiDao.prod::set_id(string)

  IL_003f:  nop

  IL_0040:  ldloc.2

  IL_0041:  ldstr      "111"

  IL_0046:  callvirt   instance void NetNiBiXiuZhiDao.prod::set_name(string)

  IL_004b:  nop

  IL_004c:  ldloc.2

  IL_004d:  callvirt   instance void class [mscorlib]System.Collections.Generic.List`1<class NetNiBiXiuZhiDao.prod>::Add(!0)

  IL_0052:  nop

  IL_0053:  ldarg.1

  IL_0054:  ldarg.1

  IL_0055:  ldind.ref

  IL_0056:  ldloc.0

  IL_0057:  call       class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0> [System.Core]System.Linq.Enumerable::Concat<class NetNiBiXiuZhiDao.prod>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>,

                                                                                                                                                              class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>)

  IL_005c:  call       class [mscorlib]System.Collections.Generic.List`1<!!0> [System.Core]System.Linq.Enumerable::ToList<class NetNiBiXiuZhiDao.prod>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>)

  IL_0061:  stind.ref

  IL_0062:  ret

} // end of method hellowordle::Myclo

 

通过上面的代码我们看以看出:

通过ref传址的时候,在执行Concat之前会先去执行ldind.ref

把ref传入的地址压栈,然后Concat出来的新数组会被放入ref传入地址的托管堆里面

然后通过stind.ref保存ref传入地址对应托管堆位置的值

总结:

也就是说:在使用引用类型传址的时候,如果在另外一个方法里面只是对传入的引用类型进行修改或者增加哪可以不用ref传入的引用类型会跟着变化,但是如果在方法里面要对传入的引用类型赋新的地址,哪一定要用ref,不然的情况下,你在方法里面的操作是无效的

(这也是按值传递和引用传递的一个很大的区别)

posted @ 2013-12-17 16:32  瀚海行舟  阅读(139)  评论(0编辑  收藏  举报