c#中使用ref和out传值

首先,如果不使用这两个关键字,那是什么样 呢?
看下面的例子:
使用ref:
using System;
class Test
{
    static void Swap(ref int x, ref int y)
    {
        int temp = x;
        x = y;
        y = temp;
    }
    
    static void Main()
    {
        int i = 1, j = 2;
        Swap(ref i, ref j);
        Console.WriteLine("i = {0}, j = {1}", i, j);         
    }
}

  程序经编译后执行输出:

i = 2, j = 1
不使用:
using System;
class Test
{     
    static void Swap(int x,int y)
    {
        int temp = x;
        x = y;
        y = temp;
    }
    static void Main()
    {
        int i = 1, j = 2;
        Swap(i,j);
        Console.WriteLine("i = {0}, j = {1}", i, j);
    }
}

  程序经编译后执行输出:
i = 1, j = 2;
比较这两个里子很明显,使用了ref关键字的函数调用以后,i和j的值变化了.而没有使用ref的却没有变,为什么呢?
请看下面这段话:
  方法的参数是个值得特别注意的地方。方法的参数传递有四种类型:传值(by value),传址(by reference),输出参数(by output),数组参数(by array)。传值参数无需额外的修饰符,传址参数需要修饰符ref,输出参数需要修饰符out,数组参数需要修饰符params。传值参数在方法调用过程中如果改变了参数的值,那么传入方法的参数在方法调用完成以后并不因此而改变,而是保留原来传入时的值。传址参数恰恰相反,如果方法调用过程改变了参数的值,那么传入方法的参数在调用完成以后也随之改变。实际上从名称上我们可以清楚地看出两者的含义--传值参数传递的是调用参数的一份拷贝,而传址参数传递的是调用参数的内存地址,该参数在方法内外指向的是同一个存储位置。
所以我们可以看出,平时我们写的函数参数是传值参数(传值参数无需额外的修饰符),不论他是值类型还是引用类型.你可以试这个例子(这个例子是对"不论他是值类型还是引用类型"这句话,):
using System;
class Test
{     
    static void Swap(string x,string y)
    {
        string temp = x;
        x = y;
        y = temp;
    }
    static void Main()
    {
        string i = "1", j = "2";
        Swap(i,j);
        Console.WriteLine("i = {0}, j = {1}", i, j);
    }
}

  程序经编译后执行输出:
i = "1", j = "2";
注意:string类型是引用类型.
i,j的值并没有改变,说明引用类型作为函数参数时,只要不加ref或者out,那他仍然是传值参数(我一直以为值类型作为函数参数时是传值参数,而引用类型作为函数参数时是传址参数).
.net框架程序设计(修订版)上有这样一句话:ref和out的区别是参数的初始化和参数返回,
可是这里说out是输出参数,那加out是传址参数吗?要不,怎么也会变呢(应该也是吧,可能他只是一个名字,可以理解成输出参数也是传址参数)?
using System;
class Test
{
    static void Swap(out int x, out int y)
    {
        int temp = x;
        x = y;
        y = temp;
    }
    
    static void Main()
    {
        int i = 1, j = 2;
        Swap(out i, out j);
        Console.WriteLine("i = {0}, j = {1}", i, j);         
    }
}
程序经编译后执行输出:

i = 2, j = 1
总结:传值参数传递的是调用参数的一份拷贝,而传址参数传递的是调用参数的内存地址,该参数在方法内外指向的是同一个存储位置.
这句话可以这样说更加明白:传值参数传递的是调用参数的拷贝的地址,该参数在方法内外指向的不是是同一个存储位置,而传址参数传递的是调用参数的内存地址,该参数在方法内外指向的是同一个存储位置

下面是我对2个参数测试结果:

代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ref_out
{
    class Program
    {
        static void Main(string[] args)
        {
            int a, b;
            //使用out传值前实参可以不赋值,即使赋值也没用,也会被清空
            outTest(out a, out b);
            Console.Write("a={0},b={1}", a, b);

//即使赋值也没用,也会被清空
            int c = 1, d = 2;
            outTest(out c, out d);
            Console.Write("a={0},b={1}", c, d);

//int e, f;//错误:ref使用前,变量必须赋值 
            //ref使用前,变量必须赋值 
            int e = 1, f = 2;
            refTest(ref e, ref f);
            Console.WriteLine("e={0};f={1}", e, f);

}
        static void outTest(out int x, out int y)
        {
            //定义out参数的时候就需要对参数进行赋值,即参数需要初始化
            x = 100; y = 20;
        }
        static void refTest(ref int x, ref int y)
        {
            //x,y 可以不赋值,参数可以不初始化,把下面注释掉也可以
            x = 100; y = 200;
        }
    }
}

1、使用ref型参数时,传入的参数必须先被初始化。对out而言,必须在方法中对其完成初始化。

2、使用ref和out时,在方法的参数和执行方法时,都要加Ref或Out关键字。以满足匹配。

3、out适合用在需要retrun多个返回值的地方,而ref则用在需要被调用的方法修改调用者的引用的时候。

注:在C#中,方法的参数传递有四种类型:传值(by value),传址(by reference),输出参数(by output),数组参数(by array)。传值参数无需额外的修饰符,传址参数需要修饰符ref,输出参数需要修饰符out,数组参数需要修饰符params。传值参数在方法调用过程中如果改变了参数的值,那么传入方法的参数在方法调用完成以后并不因此而改变,而是保留原来传入时的值。传址参数恰恰相反,如果方法调用过程改变了参数的值,那么传入方法的参数在调用完成以后也随之改变。实际上从名称上我们可以清楚地看出两者的含义--传值参数传递的是调用参数的一份拷贝,而传址参数传递的是调用参数的内存地址,该参数在方法内外指向的是同一个存储位置。

方法参数上的 ref 方法参数关键字使方法引用传递到方法的同一个变量。当控制传递回调用方法时,在方法中对参数所做的任何更改都将反映在该变量中。

若要使用 ref 参数,必须将参数作为 ref 参数显式传递到方法。ref 参数的值被传递到 ref 参数。

传递到 ref 参数的参数必须最先初始化。将此方法与 out 参数相比,后者的参数在传递到 out 参数之前不必显式初始化。

属性不是变量,不能作为 ref 参数传递。

如果两种方法的声明仅在它们对 ref 的使用方面不同,则将出现重载。但是,无法定义仅在 ref 和 out 方面不同的重载。

out

方法参数上的 out 方法参数关键字使方法引用传递到方法的同一个变量。当控制传递回调用方法时,在方法中对参数所做的任何更改都将反映在该变量中。

当希望方法返回多个值时,声明 out 方法非常有用。使用 out 参数的方法仍然可以返回一个值。一个方法可以有一个以上的 out 参数。

若要使用 out 参数,必须将参数作为 out 参数显式传递到方法。out 参数的值不会传递到 out 参数。

不必初始化作为 out 参数传递的变量。然而,必须在方法返回之前为 out 参数赋值。

属性不是变量,不能作为 out 参数传递。

posted on 2009-12-15 23:34 搏击的小船 阅读(...) 评论(...) 编辑 收藏

转载于:https://www.cnblogs.com/guanjie20/archive/2009/12/15/1625181.html

c#中使用ref和out传值相关推荐

  1. C#中关键字ref与out的区别(转)

    C#中关键字ref与out的区别(转) 在C#中,ref与out是很特殊的两个关键字.使用它们,可以使参数按照引用来传递. 总的来说,通常我们向方法中传递的是值.方法获得的是这些值的一个拷贝,然后使用 ...

  2. C++中的参数传递方式:传值、传地址、传引用总结

    指针:指针是一个变量,只不过这个变量中存储的是一个地址,指向内存中的一个单元. 引用:引用和原变量是同一个东西,只不过是原变量的一个别名. int a = 10; 定义一个整型变量aint *p = ...

  3. Vue3 Composition API(二)——computed、watchEffect、setup中使用ref

    一.computed 在前面我们讲解过计算属性computed:当我们的某些属性是依赖其他状态时,我们可以使用计算属性来处理 在前面的Options API中,我们是使用computed选项来完成的: ...

  4. matlab中rowref的意思,Excel 中出现#REF是什么意思?(excel表格复制数据显示ref)

    EXCEL表格复制到另一表格的标签页中,全部显示为REF 应该是公式单元格出现了REF, 这是公式引用单元格缺失导致的.表格整体复制的话,如果表格中有引用到其他工作表中的内容,还是会让你作选择的. E ...

  5. Vue 中的 ref 属性详解

    Vue 中的 ref 属性详解 我们先来读一下vue的官方文档 我们来分析官方文档 首先ref的引用是相当于一个DOM节点(如果是子组件则指向的是其实例),而且是一个string类型的值. 通俗的将就 ...

  6. Vue中的ref是做什么的?

    Vue 中的 ref 属性详解_前端大猪草的博客-CSDN博客 Vue 中的 ref 属性详解 我们先来读一下vue的官方文档 我们来分析官方文档 首先ref的引用是相当于一个DOM节点(如果是子组件 ...

  7. 在iview中使用ref主要事项:

    在iview中使用ref主要事项: 在我开发中遇到一个需求:在2个表格嵌套的情况下按下回车键获取下一个input框的焦点 案例: ref的深入理解: //js document.getElements ...

  8. vue中,兄弟组件之间传值

    vue中,兄弟组件之间传值 项目中,需要使用多个子组件,当需要传递值的时候,较为麻烦,怎样实现呢 1.一般可以使用子组件a传递给父组件,再由父组件传递给子组件b.但是一般较为麻烦, 2.使用bus作为 ...

  9. setup中使用ref

    目录 一.问题 二.解决方法 三.总结 一.问题 1.在选项式API中可以直接用 this.$refs.xxx来引用template中的DOM元素. 但是在组合式API setup中没有this,该如 ...

最新文章

  1. C#编程(四十四)----------string和stringbuilder
  2. android dialog加载中动画效果
  3. iPhone/iOS图片相关(读取、保存、绘制、其它相关)
  4. 程序员都怎么过端午节?
  5. android sqlite 操作类封装,[Android] Sqlite 数据库操做 工具封装类
  6. EPOLLOUT/EPOLLIN事件触发的条件
  7. python会内存泄漏吗_Python内存泄漏和内存溢出的解决方法
  8. 关于虚拟化 云计算
  9. Go---第六章:方法(小知识点笔记)
  10. CI框架 where 跟 OR 怎么连用
  11. win11没有扫雷了?咱用python做一个(效果演示+源码分享)
  12. m451dn linux驱动下载,惠普m451dn驱动下载-惠普hp m451dn打印机驱动下载 v61.120.04官方版--pc6下载站...
  13. eterm协议指令解析
  14. Typora设置高亮
  15. 微信小程序audio的简单实用
  16. 信息服务器在哪里打开,internet信息服务(lls)管理器在哪里打开
  17. SpringBoot、SpringCloud版本中GA/PRE/SNAPSHOT的详解
  18. 不懂量子力学?那你可以试试在家里做这五个实验!
  19. JAVA最佳学习方法
  20. 大学英语四级考试必读必备

热门文章

  1. FPGA专有名词的积累
  2. 一个有意思的CStatic和combobox以及Cedit控件结合使用
  3. python可以做二维码吗_Python制作二维码,并且可以添加logo
  4. python list转换成树形结构_python递归查询菜单并转换成json实例
  5. hbase 查询固定条数_HBase原理深入
  6. 光遇服务器维护都在干什么,光遇:全图毕业后该做什么?老玩家建议,这四件事不做会后悔...
  7. c语言程序后退_c语言中向后退一格是啥符号?
  8. 十万个为什么儿童版_把中国科技传播至阿语地区,少儿社《十万个为什么》阿拉伯文版亮相童书展...
  9. iOS下载大型文件原理解析三
  10. python面向对象初识