学过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引用,而不是其副本。

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. 1033. Labyrinth(dfs)

    1033 简单dfs 有一点小小的坑 就是图可能不连通 所以要从左上和右下都搜一下 加起来 从讨论里看到的 讨论里看到一句好无奈的回复 “可不可以用中文呀...” #include <iostr ...

  2. 纯tarjan poj2186

    tarjan,叙叙旧咯 #include<cstdio>#define maxn 50005int e[maxn],ne[maxn],be[maxn],all;int DFN[maxn], ...

  3. UVa 10870 (矩阵快速幂) Recurrences

    给出一个d阶线性递推关系,求f(n) mod m的值. , 求出An-dv0,该向量的最后一个元素就是所求. #include <iostream> #include <cstdio ...

  4. LA 3510 (置换 循环分解) Pixel Shuffle

    思路挺简单的,题目中的每个命令(包括命令的逆)相当于一个置换. 用O(n2k)的时间复杂度从右往左求出这些置换的乘积A,然后求m使Am = I(I为全等置换) 还是先把A分解循环,m则等于所有循环节长 ...

  5. CodeForces Round #278 (Div.2) (待续)

    A 这么简单的题直接贴代码好了. #include <cstdio> #include <cmath> using namespace std; bool islucky(in ...

  6. hdu 4671 Backup Plan(签到题)

    错成那样,还以为是卡时间卡精度的变态题,结果就那么ac了= = 悔死我了 题意就不概述了,只要处理前两列即可.其中第一列顺序直接扫一遍,第二列要先处理较少的那几种.我是接着第一列用 head[] 继续 ...

  7. Xcode中如何启用或禁用某些文件的ARC

    经常会有工程中涉及到第三方的代码, 但这些代码有的是ARC的, 有的不是. 这样的话, 在与你的工程中集成的时候就会出现问题. 如果你的工程是开启ARC的, 那就需要对某些文件禁用ARC, (-fno ...

  8. 一天一个Java基础——序列化

    1.概念 Java的“对象序列化”能将一个实现了Serializable接口的对象转换成一组byte,这样日后要用这个对象的时候,能把这些byte数据恢复出来,并据此重新构建那个对象. 对象序列化能实 ...

  9. HashMap的两种遍历方式

    HashMap的两种遍历方式 HashMap存储的是键值对:key-value . java将HashMap的键值对作为一个整体对象(java.util.Map.Entry)进行处理,这优化了Hash ...

  10. android直接读取数据库文件

    public class Dictionary extends Activity  implements OnClickListener, TextWatcher{     private final ...