c#中使用ref和out传值

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个参数测试结果:

  

 

ExpandedBlockStart.gif代码
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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/264099.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python临床数据_从临床试验中获取数据

我正在开发一个小Python函数来从clinicalTrials.gov中获取数据。从每个研究记录中,我想从中找出研究的目标条件。例如,对于this研究记录,我需要以下内容:conditions [Rhinoconjunctivitis, Rhinitis, Conjunctivitis. Allergy]然…

Jass 技能模型定义(转)

Jass是什么?先阐释一下什么是jass吧,百度:JASS(正确地说是JASS 2)是魔兽3的程序语言,用于控制游戏和地图的进行,也是魔兽游戏和地图的基础。 地图编辑器中摆放的单位(Unit),区域(Reg…

[原]第一次遭遇Oracle的Bug,纪念一下 |ORA-00600 kmgs_pre_process_request_6|

今天尝试调整一下Oracle的Large Pool Size,希望使rman的速度提升, alter system set large_pool_size80m ; 突然Oracle 实例挂掉了,查看alert file 发现如下 Wed Dec 16 11:14:49 2009 Errors in file /u01/app/admin/mydb/bdump/mydb_mman_…

表格过滤器_不用记账软件也可以记录支出明细,这个在线协同表格很方便

像我们这种中小团队,以前就用 Excel 来记录团队日常的一些支出情况,虽然有很多模板可以套用,但感觉还是有些不便之处,比如在表格里无法记录太多文字;添加发票凭证也不方便;对于不同数据的切换查看也缺乏灵活…

喜马拉雅第三方客户端开发(接口和接口数据解析)。

前言:最近闲来无事,看了网上豆瓣的第三方客户端,手有点痒,决定自己动手开发一个客户端,比较了荔枝和喜马拉雅,决定开发喜马拉雅的第三方客户端。 客户端使用了WPF开发。 1.抓取接口; 首先得解决…

life list 2010

1. water -1.no water-warm water.less 2. anything - very kindly 3. clean - any room. 4.money is working,no lazy. 转载于:https://www.cnblogs.com/byeday/archive/2009/12/16/1625902.html

聚合复合_聚合复合微生物菌剂的功能

不点蓝字关注我飞走啦!在经营肥料上来讲,大家都知道做复合微生物菌剂,不仅可以活化疏松土壤,而且在各种作物上抗逆、防病、增产的效果都非常的好。问为什么说大家都要重点使用聚合微生物菌剂呢?答因为聚合微生物菌剂和…

Linux命令 — 设置或查看网络配置命令ifconfig

1. 命令介绍命令格式:ifconfig 【interface】 【options】address主要参数:interface:网络接口名up:打开网络接口down:关闭网络接口broadcast:设置网络接口的广播地址netmask:设置网络接口的子网…

代理模式详解(静态代理和动态代理的区别以及联系)

原文链接:https://www.cnblogs.com/takumicx/p/9285230.html 1. 前言 代理模式可以说是生活中处处可见。比如说在携程上定火车票,携程在这里就起到了一个代理的作用,比起我们在官网上或者直接去柜台订票,携程可以为用户提供更多人性化的选择。再比如代购,我自己的mb…

unity自动生成敌人_unity 2d AI 敌人 自动追踪(1)

今天介绍第一种只靠 c# 代码的 简单 AI 敌人 追踪方法:简单粗暴 ,上代码1,新建对象2,代码如下:using System.Collections;using System.Collections.Generic;using UnityEngine;public class AI : MonoBehaviour{publi…

一个简单的HelloWorld程序

/* * 编译器:  VC6.0 * 类 型:  C语言 */ 1 #include <stdio.h>//#includes代表是C预处理指令,stdio.h代表是在此行位置键入了库文件stdio.h的完整内容,是标准输入输出头文件,< and >代表是直接从库文件加载stdio.h文件。2 3 intmain(void)//int代表此main…

sass 安装配置和使用

一、什么是SASSSASS在CSS的基础上做了一些扩展&#xff0c;使用SASS你可以使用一些简单的编程思想进来编写CSS。比如&#xff0c;SASS中可以定义变量、混合、嵌套以及 函数等功能。只不过SASS不像CSS&#xff0c;可以直接运用到项目中&#xff0c;如果你需要将样式运用到项目中…

为什么我的对象被 IntelliJ IDEA 悄悄修改了?

背景 最近&#xff0c;在复习JUC的时候调试了一把ConcurrentLinkedQueue的offer方法&#xff0c;意外的发现Idea在debug模式下竟然会 “自动修改” 已经创建的Java对象&#xff0c;当时觉得这个现象很是奇怪&#xff0c;现在把问题的原因以及解决过程记录下来&#xff0c;希望你…

python加密程序_Python加密程序

展开全部alpabcdefghijklmnopqrstuvwxyz0123456789 def num2alp(c):a alp[c]return(a)def alp2num(d):if d ! :return((ord(d)-97)%37)else:return 36def envVigenere(key,plaintext):m len(plaintext)n len(key)etext ""for i in range(m):p plaintext[i]k k…

如何判断网通、电信、铁通IP地址分配段

从http://ftp.apnic.net/apnic/dbase/tools/ 获取地址 shell> wget http://ftp.apnic.net/apnic/dbase/tools/ripe-dbase-client-v3.tar.gz shell> tar xzvf ripe-dbase-client-v3.tar.gz shell> cd whois-3.1 shell> ./configure shell> make 完成上述编译安…

​std::multimap

2019独角兽企业重金招聘Python工程师标准>>> std::multimap multimap,是一个关联性容器,用于存放这样的元素,这些元素是由键以及关联的值组成.容器内容将根据元素的键进行排序.并且容器可以插入多个具有相同键的元素.接口 pair<const_iterator,const_iterator>…

python调用msfconsole全自动永恒之蓝攻击_MSF之MS17-010永恒之蓝漏洞利用

Loading...请注意&#xff0c;本文编写于 392 天前&#xff0c;最后修改于 116 天前&#xff0c;其中某些信息可能已经过时。# MSF之MS17-010永恒之蓝漏洞利用1. 准备阶段2. 扫描漏洞3. 漏洞攻击---## 准备阶段**实验准备环境&#xff1a;**攻击机&#xff1a;虚拟机kali系统IP…

容器部署解决方案Docker

一、Docker简介 1.1 虚拟化 【什么是虚拟化】 在计算机中&#xff0c;虚拟化&#xff08;英语&#xff1a;Virtualization&#xff09;是一种资源管理技术&#xff0c;是将计算机的各种实体资源&#xff0c;如服务器、网络、内存及存储等&#xff0c;予以抽象、转换后呈现出来&…

BREW做的第一个程序--Hello world!

这几天开始做BREW开发了&#xff0c;刚开始挺晕的。又是C指针&#xff0c;又是BREW的SDK文档&#xff0c;还有环境配置&#xff0c;一大堆东东&#xff0c;真是让人手忙脚乱。好不容易配好了环境&#xff0c;写出了第一个Hello world!程序。感觉还不错&#xff0c;就把代码和想…

careercup-链表 2.1

2.1 编写代码&#xff0c;移除未排序链表中的重复节点。 不使用临时缓存&#xff1a; 如果不允许使用临时的缓存(即不能使用额外的存储空间)&#xff0c;那需要两个指针&#xff0c; 当第一个指针指向某个元素时&#xff0c;第二个指针把该元素后面与它相同的元素删除&#xff…