分享

C# 深度解说值传参和引用传参的原理

 kittywei 2012-02-29

此例子是我在其他园友的帖子上看到的发表一下自己的看法。

例子一

双击代码全选
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
using System;
class Element
{
    public int Number=10;
}
class Test
{
    static void Change(Element s)
    {
        s.Number=100;
    }
    static void Main()
    {
        Element e=new Element();
        Console.WriteLine(e.Number);
        Change(e);
        Console.WriteLine(e.Number);
    }
}

程序经编译后执行输出:

  10   100   

例子二

双击代码全选
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
using System;
  class Element
  {
      public int Number=10;
  }
    
  class Test
  {
      static void Change(Element s)
      {
          Element r=new Element();
          r.Number=100;
          s=r;
      }
      static void Main()
      {
          Element e=new Element();
    
          Console.WriteLine(e.Number);
          Change(e);
          Console.WriteLine(e.Number);
      }
  }
    
    
程序经编译后执行输出:
    
  10
  10

看到上面两个例子,大家心里都有一个疑问那就是为什么第一个例子输出了100 而第二个例子输出的还是10。那就让我给大家解答解答,

我们先了解一下值传和引用传的真正原理:

在经常情况下大家都会认为,值类型的参数就是传值,引用类型的参数就是。其实不是这样的。真正的原理是这样,无论参数是什么类型,值传是参数前面不加ref或out,而引用传参是在参数面前加上ref或out。

 那么到底什么是真正的值传和引用传呢,例如上边的代码两个例子其实都是值传。当new一个e的对象时在线程堆栈里分配了一块内存e(实参)保存e对象的 在托管堆的内存地址。而在调用Change(e);的时候,因为没有ref或out修饰在线程堆栈又分配了一块内存空间e(形参)也就就是e的一个拷贝内 存块,两个e保存的都是e对象的地址,都指向同一个对象。

当在参数前面没有ref或out时,启用的是e形参也就是拷贝的内存。在方法change里面其 实用的是形参,在第二例子里,当你给s复制时,其实是把r复制给形参e并没有复制给实参e,所以当方法执行之后,实参的值根本就没有改变。而我们再 main方法里用的e实参,所以Number的值没有改变。

如果想在第二例子里调用change后输出100,那只有一个办法在方法声明的时候用ref或out来修饰参数,而这时候传就不是托管堆的地址了传的是实参e的内存地址。

那么第一个例子为什么Number的值会变呢?因为在实参和形参存的都是同一个内存地址,而对象又都存在托管堆内存中,无论你是通过形参还是实参都是修改这个内存中属性的值,所以最后在第一个例子中Number变了。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多