c#方法中调用参数的值传递方式和引用传递方式以及ref与out的区别深入解析

复制代码 代码如下:

#define Test

using System;

namespace Wrox.ProCSharp.ParameterTestSample
...{

class ParemeterTest
 ...{
    static void TestInt(int[] ints,int i)
    ...{
        ints[0] = 100;
        i = 100;
    }

static void TestInt(int[] ints, ref int i)
     ...{
         ints[0] = 200;
         i = 200;
     }

static void TestInt2(int[] ints, out int i)
    ...{
        ints[0] = 300;
        i = 300;
    }

public static void Main()
    ...{
        int i=0;
        int[] ints = ...{0,1,2,3,4};

Console.WriteLine("-----------TestInt------------------");

Console.WriteLine("i={0}",i);
        Console.WriteLine("ints[0]={0}",ints[0]);
        Console.WriteLine("------------------------------------");

//默认情况下,c#所有参数都是通过值引用的,所以值类型i在上面的函数调用时,传送的只是一个副本,函数只是在调用过程中影响了副本的值,对i值实际并没有影响
        TestInt(ints, i);

Console.WriteLine("i={0}",i);//这里输出的i值仍然是0
        Console.WriteLine("ints[0]={0}",ints[0]);
        Console.WriteLine("------------------------------------");

//如果要改变i的值,可以用ref让参数i通过引用传送给函数
        TestInt(ints, ref i);

Console.WriteLine("i={0}",i);//这里输出的i值为200
        Console.WriteLine("ints[0]={0}",ints[0]);
        Console.WriteLine("------------------------------------");

//要改变i的值,也可以通过out关键字让
        TestInt2(ints, out i);

Console.WriteLine("i={0}", i);//这里输出的i值为300
        Console.WriteLine("ints[0]={0}", ints[0]);
        Console.WriteLine("------------------------------------");

//ref与out很相似,但有也区别,ref必须要求参数初始化,out则不需要
        #if Test//要测试下面的二行,把代码第一行#define Test去掉注释即可
            int j;       
            SomeFunction(ints, ref j);//编译时会报错: 使用了未赋值的局部变量“j”
        #endif

int k;
        TestInt2(ints, out k);
        Console.WriteLine("k={0}", k);
        Console.WriteLine("------------------------------------");

Console.ReadLine();
    }
 }

}

运行结果;
-----------TestInt------------------
i=0
ints[0]=0
------------------------------------
i=0
ints[0]=100
------------------------------------
i=200
ints[0]=200
------------------------------------
i=300
ints[0]=300
------------------------------------
k=300
------------------------------------

时间: 2013-07-24

asp.net(c#)ref,out ,params的区别

NO.1 params 一个可以让方法(函数)的拥有可变参数的关键字. 原则:在方法声明中的 params 关键字之后不允许任何其他参数,并且在方法声明中只允许一个 params 关键字. 示例(拷贝到vs2005中即可用,下面不再说明) 复制代码 代码如下: public partial class Form1 : Form { public static void UseParams(params int[] list) { string temp = ""; for (int i

C#方法中参数ref和out详解

一.C#方法中参数类型 有4种参数类型,有时候很难记住它们的不同特征,下图对它们做一个总结,使之更容易比较和对照. 二.C#方法中的参数 1.值参数 使用值参数,通过复制实参的值到形参的方式把数据传递到方法.方法调用时,系统做如下操作: · 在栈中为形参分配空间 · 复制实参到形参 注:栈(先进后出)是编译期间就分配好的内存空间,因此你的代码中必须就栈的大小有明确的定义: 堆(队列优先,先进先出)是程序运行期间动态分配的内存空间,你可以根据程序的运行情况确定要分配的堆内存的大小. /// <su

详解C#中的out和ref

要想充分理解C# out和ref,必须先明确如下两个概念(对值类型与引用类型掌握比较好的,可以跳过"一.明确两个基本概念") 一.明确两个基本概念 值类型: 定义:通过值的方式来传递,即实际参数向形式参数传递(关于形参和实参术语,这里不定义). 存储方式:主要在栈中. 本质:通过值传递,copy副本形式,调用栈的Pop()和Push()方法来实现. 常见类型:int,float,bool,enum,struct,Array等. 值类型例子: //主函数 static void Main

C#中out与ref的区别实例解析

本文实例讲述了C#中Out与Ref的区别,可以加深C#程序设计人员对Out和Ref用法的理解,具体分析如下: 一.区别分析: Out和Ref作为参数传递到方法体中,所传递的都是引用地址,两者在操作上本身没有区别. 但Out传递到方法体时,参数会清空,这意味着在方法体内使用Out参数前必须赋值. 而Ref传递到方法体时,其参数也是一起被传递进来,所以作为Ref参数传递,方法体中可以不对其参数赋值. 二.实例代码如下: class Program { /*ref是有进有出,out是只出不进*/ st

解析C#中的ref和out参数

很多初学者(甚至是工作一定时间的开发人员),在遇到ref或者out参数时,总会有点"晕乎乎"或者疑惑,也不知道到底该在啥时候,啥场景下使用ref或者out参数. 本文将通过实例和说明,给大家详细讲解C#中的ref和out参数. 复制代码 代码如下: using System;using System.Collections.Generic;using System.Linq;using System.Text; namespace RefAndOut{    class Program

C#中ref和out的区别浅析

在C#中通过使用方法来获取返回值时,通常只能得到一个返回值.因此,当一个方法需要返回多个值的时候,就需要用到ref和out,那么这两个方法区别在哪儿呢? MSDN:        ref 关键字使参数按引用传递.其效果是,当控制权传递回调用方法时,在方法中对参数所做的任何更改都将反映在该变量中.若要使用 ref 参数,则方法定义和调用方法都必须显式使用 ref 关键字.       out 关键字会导致参数通过引用来传递.这与 ref 关键字类似,不同之处在于 ref 要求变量必须在传递之前进行

C#中按引用传递与按值传递的区别,以及ref与out关键字的用法详解

复制代码 代码如下: /给三个整数从小到大排序并求和及其平均值//其中,三个待求整数及其排序的结果由引用参数传递:其和由输出参数传递:平均值由返回值返回.//在Main()方法中实现三个待求整数的输入及结果的输出//目的:定义方法:调用方法::理解形参和实参的引用传递关系:熟悉引用参数和输出参数的使用.using System;class Class1 {   //x,y,z是形参,按值传递   static void Sort(int x, int y, int z)    {      in

详解C#中三个关键字params,Ref,out

关于这三个关键字之前可以研究一下原本的一些操作 using System; using System.Collections.Generic; using System.Text; namespace ParamsRefOut { class Program { static void ChangeValue(int i) { i=5; Console.WriteLine("The ChangeValue method changed the value "+i.ToString())

一看就懂:图解C#中的值类型、引用类型、栈、堆、ref、out

C# 的类型系统可分为两种类型,一是值类型,一是引用类型,这个每个C#程序员都了解.还有托管堆,栈,ref,out等等概念也是每个C#程序员都会接触到的概念,也是C#程序员面试经常考到的知识,随便搜搜也有无数的文章讲解相关的概念,貌似没写一篇值类型,引用类型相关博客的不是好的C#程序员.我也凑个热闹,试图彻底讲明白相关的概念. 程序执行的原理 要彻底搞明白那一堆概念及其它们之间的关系似乎并不是一件容易的事,这是因为大部分C#程序员并不了解托管堆(简称"堆")和线程栈(简称"栈

C#编程中使用ref和out关键字来传递数组对象的用法

在 C# 中,数组实际上是对象,而不只是像 C 和 C++ 中那样的可寻址连续内存区域. Array 是所有数组类型的抽象基类型. 可以使用 Array 具有的属性以及其他类成员. 这种用法的一个示例是使用 Length 属性来获取数组的长度. 下面的代码将 numbers 数组的长度(为 5)赋给名为 lengthOfNumbers 的变量: int[] numbers = { 1, 2, 3, 4, 5 }; int lengthOfNumbers = numbers.Length; Arr

实例解析C#设计模式编程中简单工厂模式的使用

简单工厂模式的介绍 说到简单工厂,自然的第一个疑问当然就是什么是简单工厂模式了? 在现实生活中工厂是负责生产产品的,同样在设计模式中,简单工厂模式我们也可以理解为负责生产对象的一个类, 我们平常编程中,当使用"new"关键字创建一个对象时,此时该类就依赖与这个对象,也就是他们之间的耦合度高,当需求变化时,我们就不得不去修改此类的源码,此时我们可以运用面向对象(OO)的很重要的原则去解决这一的问题,该原则就是--封装改变,既然要封装改变,自然也就要找到改变的代码,然后把改变的代码用类来封

Java多线程编程中synchronized关键字的基础用法讲解

多线程编程中,最关键.最关心的问题应该就是同步问题,这是一个难点,也是核心. 从jdk最早的版本的synchronized.volatile,到jdk 1.5中提供的java.util.concurrent.locks包中的Lock接口(实现有ReadLock,WriteLock,ReentrantLock),多线程的实现也是一步步走向成熟化.   同步,它是通过什么机制来控制的呢?第一反应就是锁,这个在学习操作系统与数据库的时候,应该都已经接触到了.在Java的多线程程序中,当多个程序竞争同一

浅谈Java编程中的synthetic关键字

java synthetic关键字.有synthetic标记的field和method是class内部使用的,正常的源代码里不会出现synthetic field.小颖编译工具用的就是jad.所有反编译工具都不能保证完全正确地反编译class.所以你不能要求太多. 下面我给大家介绍一下synthetic 下面的例子是最常见的synthetic field Java代码 class parent { public void foo() { } class inner { inner() { foo

举例讲解Java编程中this关键字与super关键字的用法

this 总要有个事物来代表类的当前对象,就像C++中的this指针一样,Java中的this关键字就是代表当前对象的引用. 它有三个主要的作用: 1.在构造方法中调用其他构造方法.       比如有一个Student类,有三个构造函数,某一个构造函数中调用另外构造函数,就要用到this(),而直接使用Student()是不可以的. 2.返回当前对象的引用. 3.区分成员变量名和参数名. 看下面的例子: public class Student { private String name; p

深入解析Java编程中final关键字的使用

在Java中声明属性.方法和类时,可使用关键字final来修饰.final变量即为常量,只能赋值一次:final方法不能被子类重写:final类不能被继承. 1.final成员 声明 final 字段有助于优化器作出更好的优化决定,因为如果编译器知道字段的值不会更改,那么它能安全地在寄存器中高速缓存该值.final 字段还通过让编译器强制该字段为只读来提供额外的安全级别.   1.1关于final成员赋值 1)在java中,普通变量可默认初始化.但是final类型的变量必须显式地初始化.   2

Python面向对象编程中的类和对象学习教程

Python中一切都是对象.类提供了创建新类型对象的机制.这篇教程中,我们不谈类和面向对象的基本知识,而专注在更好地理解Python面向对象编程上.假设我们使用新风格的python类,它们继承自object父类. 定义类 class 语句可以定义一系列的属性.变量.方法,他们被该类的实例对象所共享.下面给出一个简单类定义: class Account(object): num_accounts = 0 def __init__(self, name, balance): self.name =

Access出现&quot;所有记录中均未找到搜索关键字&quot;的错误解决

Microsoft JET Database Engine 错误 '80004005' 所有记录中均未找到搜索关键字. 开始一直调试是不是数据错误,Access的"压缩和修复数据库"也点了很多次,等第二次提交修改都出现问题,后来使用信息内容换成少量字符(随便几个字符),提交了N次都正常,开始还怀疑我的Access数据库是不是出问题了,怪了.百度搜索一下错误代码,发现还蛮多这样的文章,哈,找到原因了. 如果access的备注字段存在索引,当字段的内容超过1908个字节后,该记录将不可删除