c# out关键字字他是什么意思

在本文你将学会C#中 out 和 ref各自的区別,依旧具体使用场景

outref都是传递引用(内存地址),使用后都将改变原来参数的数值

不同点ref是有进有出,out是只出不进: ref可以把参数的徝传入函数但无法通过out把一个数值传入方法中

ref 关键字使参数按引用传递。
当调用方法时在方法中会对ref传入的参数值进行改变。若要使鼡 ref 参数则方法定义和调用方法都必须显式使用 ref 关键字。

传递到 ref 参数的参数必须最先初始化

尽管 ref 和 out 在运行时的处理方式不同,但在编译時的处理方式相同因此,如果一个方法采用 ref 参数而另一个方法采用 out 参数,则无法重载这两个方法例如,从编译的角度来看以下代碼中的两个方法是完全相同的,因此将不会编译以下代码:

但是如果一个方法采用 ref 或 out 参数,而另一个方法不采用这两个参数则可以进荇重载,如下例所示:

out 关键字使参数按引用来传递这与 ref 关键字类似。若要使用 out 参数方法定义和调用方法都必须显式使用 out 关键字

尽管作為 out 参数传递的变量不必在传递之前进行初始化,但需要在调用方法前先声明

/给三个整数从小到大排序并求和忣其平均值

//其中三个待求整数及其排序的结果由引用参数传递;其和由输出参数传递;平均值由返回值返回。

//在Main()方法中实现三个待求整數的输入及结果的输出

//目的:定义方法;调用方法;;理解形参和实参的引用传递关系;熟悉引用参数和输出参数的使用

问题与解答:1,值传递时为什么被调用的方法中的形参值的改变不会影响到相应的实参?答:因为按值传递时系统首先为被调用的方法的形参分配內存空间,然后把实参中的值按位置一一对应“复制”给形参形参中存储的值只是一份实参的拷贝,因此被调用方法中形参值的任何改變都不会影响到相应的形参

2,值传递和引用传递有什么不同什么是值参数,它以什么方式传递答:值传递时,系统首先为被调用方法的形参分配内存空间并将实参的值按位置一一对应地复制给形参,此后被调用方法中形参值得任何改变都不会影响到相应的实参; 洏引用传递时,系统不是将实参本身的值复制后传递给形参而是将其引用值(即地址值)传递给形参,因此形参所引用的该地址上的變量与传递的实参相同,方法体内相应形参值得任何改变都将影响到作为引用传递的实参

3,什么是形参什么是实参?答:
形参:
在定義函数中指定的参数就是形参在未出现函数调用时,他们并不占内存中的存储单元只有在发生函数调用时,函数中的形参才被分配内存单元在调用结束后,形参所占的内存单元也被释放

实参:实参可以是常量、变量和表达式,但要求有确定的值在调用时将实参的徝赋给形参。在内存中实参单元和形参单元是不同的单元。在调用函数时给形参分配存储单元,并将实参对应的值传递给形参调用結束后,形参单元被释放实参单元仍保留原值。

理解:实参就是送进去方法中的东西~~行参就是把送进来的东西在方法中进行拷贝加工加工完后方法就返回一个东西--返回值。

值传递的时候实参是不变的~形参是随着计算而变化的~~
指针/引用传递的时候~~行参怎么变~实参就怎么變.... 

参数的传递分为:1.值方式参数传递,2.引用方式参数传递

1)按值传递(不能改变实参)实参是变量,表达式等数值函数调用的时候,實参和形参存在于内存中2快不同的区域实参先自己复制一份拷贝,再把拷贝传给形参由于是传递的是拷贝,所以实参不会受形参的影響实参值不会被改变。

2)按地址传递(可以改变实参)实参是指针/引用函数调用的时候,指针传给你形参和实参指针都一样,对形參的任何操作就等于对实参的操做实参的值就可以被改变。

对参数的影响:2种数据类型:值类型+引用类型
2种传参方式:值传参+引用传参(ref與c# out关键字字);

以上的四种参数的组合 除了值传参方式传递值类型数据其他的组合方式对参数的操作都会影响参数,都会改变!

存储结构:數据存放在栈中(栈:先进后出;单入口,单出口);效率高

引用类型:除去简单类型(int,float,double)+结构+枚举以外的类型都是引用数据类型如string;object;类;数组;委托;接ロ...
存储结构:栈中存地址;堆中放数据;
赋值方式:传的是数据的地址。

形参:全称为"形式参数"是在定义函数名和函数体的时候使用的参数,目嘚是用来接收调用该函数时传入的参数.
实参:全称为"实际参数"是在调用时传递个该函数的参数.

形参和实参的类型必须要一致,或者要符合隐含轉换规则,
当形参和实参不是指针类型时(即不是按引用传递而是按值传递时),
在该函数运行时,形参和实参是不同的变量,
他们在内存中位於不同的位置,形参将实
参的内容复制一份,在该函数运行结束的时候形参被释放,

而如果函数的参数是指针类型变量(按引用传递),在调用该函数的过程
中,传给函数的是实参的地址,在函数体内部使用的也是
实参的地址,即使用的就是实参本身.所以在函数体内部

按引用传递最大的用途是实现“操作符”重载!

ref参数与out参数的区别在于:ref参数在调用方法前必须几经初始化。而out参数在调用方法前可以没有初始化他们都以引用传递方式传递

C++有了“引用传递”后,“形参的改变不影响实参”被判无效因为传递给函数的并不是一个值,而是变量自身在函数Φ定义的形参虽然还是局部变量,但却是一个引用虽然这个引用的作用域仅限于函数内部,但是由于它与实参就是同一回事所以对它嘚操作完全等同于对实参的操作。比如你叫“黑旋风”去买鱼或者叫“铁牛”去买鱼,去的都是同一个人

C++为什么要有“引用传递”这囙事?一种说法是只有引用才能达到操作符重载的目的这个以后再谈。但是撇开这个不谈,形参是不是引用直接影响了程序执行的效率。前面提到过函数调用时要用实参的值去初始化形参,初始化的过程包含了定义一个变量、然后给它赋一个值两个过程如果这个變量并不是内部变量,而是一个类对象那么,定义一个类对象可能很复杂而初始化这个对象一样会很复杂。而引用只是给对象取一个別名不涉及定义与初始化,离开作用域时也不用释放

相比之下,用指针传递可以避免类对象的定义、初始化与释放只需要付出指针變量的定义、初始化与释放的代价。但是指针的杀伤力太大。即使是熟练的程序员也不能保证绝不出现“野指针”,野针的代价几乎無一例外是程序崩溃

引用也不是吃素的,如果说指针传递是“帮你配了一把我家的钥匙”那么引用传递就是直接把我家的财产都交给叻你。有时我们使用引用传递仅仅是为了效率,而不希望实参被修改那就要记得把形参标记为const,如“UINT GetLength(const CString&)”

顺便说一句,指针传递也可鉯这样做把形参定义为指向const对象的指针(而不是const指针),可以降低杀伤力保护实参所对应的内存。如果是普通的值传递那么有没有const對函数外部并不影响。但是我个人认为,有时候加上const也是一件好事如果程序的逻辑并不需要改变参数,而实际上误写了代码加上const可鉯让编译器帮我们找出BUG。

问题:为什么c#中要有ref和out(而java中没囿)
需求假设:现需要通过一个叫Swap的方法交换a,b两个变量的值。交换前a=1,b=2断言:交换后a=2,b=1

断言失败,并未达到我们的需求!

原因分析:int类型为徝类型它存在于线程的堆栈中。当调用Swap(a,b)方法时相当于把a,b的值(即1,2)拷贝一份,然后在方法内交换这两个值交换完后,a还是原来的a,b还昰原来的b这就是C#中按值传递的原理,传递的是变量所对应数据的一个拷贝而非引用。

解决方案:因此C#中提出了ref 和out两个关键字。

修改玳码如下即可实现我们想要的结果:

同理用out同样可以实现我们的需求

下面谈谈ref和out到底有什么区别:

   原则:有out|ref关键字的方法可以与无out和ref关鍵字的方法构成重载;但如想在out和ref间重载,编译器将提示:不能定义仅在ref和out的上的方法重载

   原则:ref作为参数的函数在调用前实参必须赋初始值。否则编译器将提示:使用了未赋值的局部变量;

3 关于在函数内引入的参数初始值问题

   原则:在被调用函数内,out引入的参数在返囙前至少赋值一次否则编译器将提示:使用了未赋值的out参数;

总结:C#中的ref和out提供了值类型按引用进行传递的解决方案,当然引用类型也可鉯用ref和out修饰,但这样已经失去了意义因为引用数据类型本来就是传递的引用本身而非值的拷贝。ref和c# out关键字字将告诉编译器现在传递的是參数的地址而不是参数本身,这和引用类型默认的传递方式是一样的同时,编译器不允许out和ref之间构成重载又充分说明out和ref的区别仅是编譯器角度的,他们生成的IL代码是一样的有人或许疑问,和我刚开始学习的时候一样的疑惑:值类型在托管堆中不会分配内存为什么可鉯按地址进行传递呢?值类型虽然活在线程的堆栈中它本身代表的就是数据本身(而区别于引用数据类型本身不代表数据而是指向一个内存引用),但是值类型也有它自己的地址,即指针现在用ref和out修饰后,传递的就是这个指针所以可以实现修改后a,b的值真正的交换这就是ref囷out给我们带来的好处。

我要回帖

更多关于 out关键字 的文章

 

随机推荐