学过C#的人都知道,通过或通过引用,值类型和引用类型都可以作为方法参数传递。在C#中,不管是值类型或者是引用类型,所有方法参数在默认情况下是通过值传递的。

1)通过值传递值类型
在通过值传递作为方法参数的变量时,传递给方法的是数据副本。在方法中对该数据的任何修改都不会对初始值有任何影响
C#如下代码:

  1. using System;
  2. class MyExecutableClass
  3. {
  4. static void Main(string[] args)
  5. {
  6. int value=50;
  7. DoSometing(value);
  8. Console.WriteLine(value);
  9. }
  10. static void DoSomething(int parameter)
  11. {
  12. parameter=100;
  13. }
  14. }

程序的输出为50.也许你会感到奇怪,为什么不是100呢?因为变量value是通过值而不是引用传递的。我们不需要添加任何特殊的关键字,而是依赖于C#的默认行为,通过值传递值类型。

2)通过引用传递值类型
通过引用传递值类型,也就是说传递值(变量)的引用。如果传递引用的话,那么无论在程序的什么地方作改变的话(可能是在另一个方法、属性中,甚至是另一个对象中),都会改变使用改引用的值。对方法中任何参数的改变都将影响方法的返回值。
在C#中,通过引用传递是通过ref关键字实现的,必须按如下所示将ref关键字添加到方法定义中:
static void DoSomething(ref int parameter)
传递参数时,必须使用ref关键字。
DoSomething(ref value)
下面的代码演示了如何对值类型使用ref关键字:

  1. using System;
  2. class MyExecutableClass
  3. {
  4. static void Main(string[] args)
  5. {
  6. int value=50;
  7. DoSomething(ref value);
  8. Console.WriteLine(value);
  9. }
  10. static void DoSomething(ref int parameter)
  11. {
  12. parameter=100;
  13. }
  14. }

结果正如你所料,输出为100.

3)通过值传递引用类型
一般来说,通过值传递意味着传递存储在栈中的值。对于引用类型来说,存储在栈上的值表示对
内存中对象实际位置的引用。因此,如果通过值传递引用类型,就意味着传递的是对象的引用(它的堆栈)
.使用该引用作的改变最终会改变堆中的同一对象。
通过值传递引用类型不像通过值传递值类型---它更像通过引用传递值类型。在如下代码中,
我们将Person用作引用类型。

  1. using System;
  2. class MyExecutableClass
  3. {
  4. static void Main(string[] args)
  5. {
  6. Person person=new Person(50);
  7. DoSomething(person);
  8. Console.WriteLine(person.Age);
  9. }
  10. static void DoSomething(Person somePerson)
  11. {
  12. somePerson.Age=100;
  13. }
  14. }
  15. class Person
  16. {
  17. public int Age;
  18. public Person(int Age);
  19. {
  20. this.Age=Age;
  21. }
  22. }

运行程序,可以发现输出值为100.

如果对DoSometing方法作如下修改;

  1. static void DoSomething(Person somePerson)
  2. {
  3. somePeron=new Person(100);
  4. }

重新运行程序,发现输出为50.这是因为我们并没有将引用传递给方法?
答案是:不,我们确实发送了引用。引用类型有两个元素---引用和对象。现在,在
调用DoSomething()方法时,我们创建了一个引用副本,它仍然指向同一对象,因此,对对象的改变会影响主程序。而对引用的改变则不会,在方法结束时,消失的只是引用的副本。
1。在使用somePerson.Age属性改变年龄时,我们改变的是对象

2。但接下来是创建一个新对象,改变引用来指向它---对引用的改变将会丢失。
应该怎么做呢?方案就是通过引用传递引用类型,那样作的话,如果改变somePerson所存储的引用,那么另一个“父”引用会自动更新。听起来很混乱,下面再讨论。

4) 通过引用传递引用类型
我们知道,在通过值传递引用类型时,我们传递对内存中对象位置的引用。而通过引用传递引用类型时,我们将传递引用的引用。
正如我们所看到的,通过值传递引用类型并不适合于所有情况---特别是需要改变引用以指向新对象时。
下面例子就是说明通过引用传递就很有用。

  1. <pre name="code" class="csharp"></pre><pre name="code" class="csharp">using System;
  2. class MyExecutableClass
  3. {
  4. static void Main(string[] args)
  5. {
  6. Person person=new Person(50);
  7. DoSometing(ref person);
  8. Console.WriteLine(person.Age);
  9. }
  10. static void DoSometing(ref Person somePerson)
  11. {
  12. somePerson=new Person(100);
  13. }</pre><pre name="code" class="csharp">} </pre>
  14. <pre></pre>

这次输出为100;person变量实际上对堆上Person对象的引用。在调用DoSomething()时,编译器创建了对Person引用的引用(而不是对Person对象的引用).在DoSometing()方法中,somePerson是Person引用的引用,而Person引用堆上的对象。然而,DoSomething()知道值是通过引用传递的,因此对somePerson的任何改变实际上是改变了person。结果就是somePerson的行为就好像它是person引用,而不是其副本。

附测试代码,加深理解:

static void CallDoType()
        {
            //传递值类型
            int value = 50;
            //DoValueTransferValueType(value);
            //DoReferenceTransferValueType(ref value);
            //Console.WriteLine(value);

//传引用类型 传类
            Person person = new Person(50);
            //DoValueTransferReferenceType(person);
            DoReferenceTransferReferenceType(ref person);
            Console.WriteLine(person.Age);
        }

/// <summary>
        /// 通过值传递值类型 在通过值传递作为方法参数的变量时,传递给方法的是数据副本。在方法中对该数据的任何修改都不会对初始值有任何影响。
        /// </summary>
        /// <param name="parameter"></param>
        static void DoValueTransferValueType(int parameter)
        {
            parameter = 100;
        }

/// <summary>
        /// 通过引用传递值类型 在C#中,通过引用传递是通过ref关键字实现的
        /// </summary>
        /// <param name="parameter"></param>
        static void DoReferenceTransferValueType(ref int parameter)
        {
            parameter = 100;
        }

/// <summary>
        /// 通过值传递引用类型 一般来说,通过值传递意味着传递存储在栈中的值。对于引用类型来说,存储在栈上的值表示对内存中对象实际位置的引用。
        /// </summary>
        /// <param name="parameter"></param>
        static void DoValueTransferReferenceType(Person somePerson)
        {
            //somePerson.Age = 100;   // 输出100

//引用类型有两个元素---引用和对象。现在,在调用DoSomething()方法时,我们创建了一个引用副本,它仍然指向同一对象,因此,对对象的改变会影响主程序。
            //而对引用的改变则不会,在方法结束时,消失的只是引用的副本。
            somePerson = new Person(100);   //输出50:
            /*1。在使用somePerson.Age属性改变年龄时,我们改变的是对象。

2。但接下来是创建一个新对象,改变引用来指向它---对引用的改变将会丢失。
应该怎么做呢?方案就是通过引用传递引用类型,那样作的话,如果改变somePerson所存储的引用,那么另一个“父”引用会自动更新*/
        }
        /// <summary>
        /// 通过引用传递引用类型
        /// 在通过值传递引用类型时,我们传递对内存中对象位置的引用。而通过引用传递引用类型时,我们将传递引用的引用。
        /// </summary>
        /// <param name="parameter"></param>
        static void DoReferenceTransferReferenceType(ref Person somePerson)
        {
            somePerson = new Person(100);
        }

class Person
{
    public int Age;
    public Person(int Age)
    {
        this.Age = Age;
    }
}

C#引用传递[转]的更多相关文章

  1. Java 为值传递而不是引用传递

    ——reference Java is Pass by Value and Not Pass by Reference 其实这个问题是一个非常初级的问题,相关的概念初学者早已掌握,但是时间长了还是容易 ...

  2. call_user_func()的参数不能为引用传递 自定义替代方法

    php手册 中关于 请注意,传入call_user_func()的参数不能为引用传递. 关于这个情况的解释,可自己搜索.我们可以自己定义一个函数解决这样的问题,实例如下: <?php ini_s ...

  3. [转] C++的引用传递、指针传递参数在java中的相应处理方法

    原文出处:[http://blog.csdn.net/conowen/article/details/7420533] 首先要明白一点,java是没有指针这个概念的. 但是要实现C++的引用传递.指针 ...

  4. python 引用传递与值传递

    https://taizilongxu.gitbooks.io/stackoverflow-about-python/content/16/README.html 1.也就是如果传可变对象,就是引用传 ...

  5. java是值传递还是引用传递

    首先写一个简便的Employee,以便测试使用. class Employee { private String name; public Employee(String name) { this.n ...

  6. Java中值传递和引用传递的概念

    很多书中都提到了在Java中只存在值传递,但是今天在一个NanoHTTPD的源码中看到这样一段: if (qmi >= 0) { decodeParms(uri.substring(qmi + ...

  7. Java中引用类型变量,对象,值类型,值传递,引用传递 区别与定义

    一.Java中什么叫做引用类型变量?引用:就是按内存地址查询       比如:String s = new String();这个其实是在栈内存里分配一块内存空间为s,在堆内存里new了一个Stri ...

  8. java关于值传递和引用传递的有趣试验

    上代码: public class Demo { public static void main(String[] args) { test_1(); test_2(); } public stati ...

  9. java中值传递和引用传递

    最近工作中使用到了值传递和引用传递,但是有点懵,现在看了下面的文章后清晰多了.一下是文章(网摘) 1:按值传递是什么 指的是在方法调用时,传递的参数是按值的拷贝传递.示例如下: public clas ...

  10. Java中的值传递和引用传递

    这几天一直再纠结这个问题,今天看了这篇文章有点思路了,这跟C++里函数参数为引用.指针还是有很大区别. 当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里 ...

随机推荐

  1. (hdu step 6.3.3)Air Raid(最小路径覆盖:求用最少边把全部的顶点都覆盖)

    题目: Air Raid Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total ...

  2. 【UNIX网络编程】FIFO

    管道作为进程间通信的最古老方式,它的缺点是没有名字,因此仅仅能用在有亲缘关系的父子进程之间.对于无亲缘关系的进程间.无法用管道进行通信.FIFO能够完毕无亲缘关系的进程间的通信.FIFO也被称为命名管 ...

  3. 干货首发,能够清理,带动画的自己定义控件CuteEditText

    转载请注明出处:王亟亟的大牛之路 总想创造个什么,可是又不知道要详细做什么. 那么仅仅有丛一直用的那些东西上面開始创造,哈哈.然后再摸索的过程中进步吧. 先上一下效果: 这样的带删除button的形式 ...

  4. EMQ 压测问题

    一.单台服务器最高只能跑2W多一点问题描述 一直使用benchmark测试单台EMQ都没有超过3W链接数 一个独立的外网IP只能提供最多6W的端口号,但每个TCP需要分配一个指定的端口号.所以理论上讲 ...

  5. HDU 1695 GCD(容斥定理)

    GCD Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submis ...

  6. 虚拟键盘 input 挡住

    https://mp.weixin.qq.com/s?__biz=MjM5MTA1MjAxMQ==&mid=2651226929&idx=1&sn=4587bf582dcb23 ...

  7. java中GET方式提交和POST方式提交

    java中GET方式提交的示例: /** * 获取关注列表; * @return */ @SuppressWarnings("unchecked") public static A ...

  8. python登陆Tom邮箱的代码一例

    本文出处参考:http://www.cnblogs.com/LinuxHunter/archive/2010/11/30/1891635.html 在很多的python 教程中都会讲到登录邮箱或发送邮 ...

  9. 使用jvisualvm进行远程监控

    1. 描述 jvisualvm是JDK自带的监控工具,位于JDK bin目录下面. 默认jvisualvm不能监控远程的JVM进程,需要进行一些配置. 2. 单独在应用上配置JVM启动参数 在Java ...

  10. Xamarin for VS 4.0.1.145 Stable版免费完整破解补丁

    Xamarin for VS 4.0.1.145 Stable版免费完整破解补丁 支持Priority最高权限(超企业版)开发, 支持Android, IOS调试.  支持Android打包为Bund ...