先来说下C#中的数据类型.分值类型和引用类型两大类.

  值类型:直接存储数据的值,保存在内存中

  引用类型:存储对值的引用,实际上存储的就是一个内存的地址

  C#预定义的简单类型,像int,float,bool,char都是值类型,另外enum(枚举),struct(结构)也是值类型

  string,数组,自定义的class类、接口、委托和封装就都是引用类型了.其中的string是比较特殊的引用类型

  C#函数的参数如果不加ref,out这样的修饰符显式申明参数是通过引用传递外,默认都是值传递.

传递值类型参数

  值类型变量直接包含其数据,这与引用类型变量不同,后者包含对其数据的引用。因此,向方法传递值类型变量意味着向方法传递变量的一个副本。方法内发生的对参数的更改对该变量中存储的原始数据无任何影响。如果希望所调用的方法更改参数的值,必须使用 ref 或 out 关键字通过引用传递该参数。为了简单起见,下面的示例使用 ref

  1. 通过值传递值类型:

代码

class PassingValByVal
{
static void SquareIt(int x)
{
x *= x;
System.Console.WriteLine("The value inside the method: {0}", x); //25
}
static void Main()
{
int n = ;
System.Console.WriteLine("The value before calling the method: {0}", n); //5 SquareIt(n);
System.Console.WriteLine("The value after calling the method: {0}", n); //5
}
}
变量 n 为值类型,包含其数据(值为 5)。当调用 SquareIt 时,n 的内容被复制到参数 x 中,在方法内将该参数求平方。但在 Main 中,n 的值在调用 SquareIt 方法前后是相同的。实际上,方法内发生的更改只影响局部变量 x

2.通过引用传递值类型

下面的示例除使用 ref 关键字传递参数以外,其余与上一示例相同。参数的值在调用方法后发生更改

代码

class PassingValByRef
{
static void SquareIt(ref int x)
{
x *= x;
System.Console.WriteLine("The value inside the method: {0}", x);//25
}
static void Main()
{
int n = ;
System.Console.WriteLine("The value before calling the method: {0}", n);//5 SquareIt(ref n);
System.Console.WriteLine("The value after calling the method: {0}", n);//25
}
}

本示例中,传递的不是 n 的值,而是对 n 的引用。参数 x 不是 int 类型,它是对 int 的引用(本例中为对 n 的引用)。因此,当在方法内对 x 求平方时,实际被求平方的是 x 所引用的项:n

传递引用类型参数

  引用类型的变量不直接包含其数据;它包含的是对其数据的引用。当通过值传递引用类型的参数时,有可能更改引用所指向的数据,如某类成员的值。但是无法更改引用本身的值;也就是说,不能使用相同的引用为新类分配内存并使之在块外保持。若要这样做,应使用 ref 或 out 关键字传递参数。为了简单起见,下面的示例使用 ref

  1. 通过值传递引用类型

下面的示例演示通过值向 Change 方法传递引用类型的参数 arr。由于该参数是对 arr 的引用,所以有可能更改数组元素的值。但是,试图将参数重新分配到不同的内存位置时,该操作仅在方法内有效,并不影响原始变量 arr
代码

class PassingRefByVal
{
static void Change(int[] pArray)
{
pArray[] = ;
pArray = new int[] {-, -, -, -, -};
System.Console.WriteLine("Inside the method, the first element is: {0}", pArray[]);//-3
} static void Main()
{
int[] arr = {, , };
System.Console.WriteLine("Inside Main, before calling the method, the first element is: {0}", arr []);//1 Change(arr);
System.Console.WriteLine("Inside Main, after calling the method, the first element is: {0}", arr []);//888
}
}

在上个示例中,数组 arr 为引用类型,在未使用 ref 参数的情况下传递给方法。在此情况下,将向方法传递指向 arr 的引用的一个副本。输出显示方法有可能更改数组元素的内容,在这种情况下,从 1改为 888。但是,在 Change 方法内使用 new 运算符来分配新的内存部分,将使变量 pArray 引用新的数组。因此,这之后的任何更改都不会影响原始数组 arr(它是在 Main 内创建的)。实际上,本示例中创建了两个数组,一个在 Main 内,一个在 Change 方法内。

  2. 通过引用传递引用类型

本示例除在方法头和调用中使用 ref 关键字以外,其余与上个示例相同。方法内发生的任何更改都会影响调用程序中的原始变量
class PassingRefByRef
{
static void Change(ref int[] pArray)
{
pArray[] = ;
pArray = new int[] {-, -, -, -, -};
System.Console.WriteLine("Inside the method, the first element is: {0}", pArray[]);//-3
} static void Main()
{
int[] arr = {, , };
System.Console.WriteLine("Inside Main, before calling the method, the first element is: {0}", arr[]);//1 Change(ref arr);
System.Console.WriteLine("Inside Main, after calling the method, the first element is: {0}", arr[]);//-3
}
}

方法内发生的所有更改都影响 Main 中的原始数组。实际上,使用 new 运算符对原始数组进行了重新分配。因此,调用 Change 方法后,对 arr 的任何引用都将指向 Change 方法中创建的五个元素的数组。

C#中的引用传递、值传递的更多相关文章

  1. Java中不得不谈的值传递和地址传递

    个人的一些认识,希望能对初学Java的你,或者困惑于方法参数传递的你祈祷一丝帮助! 下面是一些作者的个人观点,如果有错,欢迎各位大牛指出错误,灰常感谢您的观看与支持... -------------- ...

  2. Java中传参的值传递和引用传递问题(转)

    今天遇到了一个java程序,需要用参数来返回值(虽然最后用另一种方法实现了),在网上看到这样一篇文章,很受启发. 本文章来自于http://hi.baidu.com/xzhilie/blog/item ...

  3. JavaScript中函数参数的值传递和引用传递

    结论: 对于数字.字符串等基本类型变量,是将它们的值传递给了函数参数,函数参数的改变不会影响函数外部的变量. 对于数组和对象等是将对象(数组)的变量的值传递给了函数参数,这个变量保存的指向对象(数组) ...

  4. c++中函数参数传递(值传递、指针传递,引用传递)进一步认识

    概念    首先从概念上来说一下这几种函数传参方式及区别:    1.值传递:形参是实参的拷贝,改变函数形参的值并不会影响外部实参的值,这是最常用的一种传参方法,也是最简单的一种传参方法,只需要传递参 ...

  5. JAVA方法中参数到底是值传递还是引用传递

    当一个对象被当作参数传递到一个方法后,在此方法内可以改变这个对象的属性,那么这里到底是值传递还是引用传递? 答:是值传递.Java 语言的参数传递只有值传递.当一个实例对象作为参数被传递到方法中时,参 ...

  6. 面试官问:Go 中的参数传递是值传递还是引用传递?

    一个程序中,变量分为变量名和变量内容,变量内容的存储一般会被分配到堆和栈上.而在 Go 语言中有两种传递变量的方式值传递和引用传递.其中值传递会直接将变量内容附在变量名上传递,而引用传递会将变量内容的 ...

  7. 引用传递&值传递

    下面的程序阐述了值传递与应用传递的区别. package com.liaojianya.chapter1; /** * This program demonstrates the use of arr ...

  8. java中为什么只存在值传递(以传入自定义引用类型为例)

    java中只有值传递 为什么这么说?两个例子: public class Student { int sage = 20; String sname = "云胡不归"; publi ...

  9. js 参数的 引用与值传递

    js中arr的赋值不影响原数组,赋值和引用的区别 1.赋值 var a = 1; var b = a;   //赋的是a的复制值 b ++; alert(a);   //"1"   ...

  10. 【温故知新C/C++/opencv】取址符&||cv::groupRectangles||引用与值传递

    cv::groupRectangles void groupRectangles(vector<Rect>& rectList, int groupThreshold, doubl ...

随机推荐

  1. API HOOK库

    API HOOK库 API HOOK有两种做法,一种是SetWindowHookEx,简单易用,但如果做其它的HOOK,如HOOK OpenProcess,就需要修改内存地址了,内存地址可以通过Wri ...

  2. Changing the working directory of VIM

    Sometimes we want to open another file in the same folder with current editing file, what we can do ...

  3. Nginx安装配置与HelloWorld

    <深入理解Nginx>阅读与实践(一):Nginx安装配置与HelloWorld 最近在读陶辉的<深入理解Nginx:模块开发与架构解析>,一是想跟着大牛练练阅读和编写开源代码 ...

  4. spring.net AOP通知类型

    上篇介绍了spring.net AOP的基本实现,其中有说到通知类型,首先在这里补充解释一下.最后出一个异常通知的实例,因为他的实现和别的通知有些不一样. 1.拦截环绕通知:在Spring中最基础的通 ...

  5. NodeJS系列-部署

    NodeJS系列-部署 NodeJS我就不介绍了,被标题吸引进来的人可以看这个链接,了解NodeJS.下来就开始关于NodeJS开发的指南. NodeJS可以部署的平台有Windows,Unix,iO ...

  6. c# 关于10进制和16进制转换以及显示

    直接举例说明: int i = 15;//一个10进制数 string txt = Convert.ToString(i,16);//将上面10进制以16进制形式显示为f string s = &qu ...

  7. python logging info -> 将服务请求记录输出

    在tornado 里面这样用 看看logging.warning() , logging.info() , 我们非常想用 zdaemon , 和 logging 将对系统的所有访问转换到服务器里面,作 ...

  8. MacOSX高分屏图片打包工具tiffutil的简单使用

    You can use the man command tiffutil with the option -cathidpicheck. The command lets you manipulate ...

  9. C#多线程,线程锁

    ];             ; i < ; i++) {                 threads[i]= ; i < ; i++) {                     R ...

  10. poj1872A Dicey Problem

    Home Problems Status Contest     284:28:39 307:00:00   Overview Problem Status Rank A B C D E F G H ...