一、方法参数的类型----值类型和引用类型

当方法传递的参数是值类型时,变量的栈数据会完整地复制到目标参数中即实参和形参中的数据相同但存放在内存的不同位置。所以,在目标方法中对形参所做的更改不会对调用者的初始变量产生任何影响。

当方法传递的参数是引用类型是,只是将变量的引用复制到目标参数中,实参和形参的引用指向内存中的同一位置。所以,在目标方法中对形参所做的更改会影响调用者的初始变量。

二、一些特殊的方法参数

1、引用参数---ref (使值类型的变量做方法参数时也可以传引用)

一些数据类型(例如类,数组等引用类型)作为方法的参数时默认是传引用的,大多数数据类型(例如结构,整数类型等值类型)在作为方法的参数时是传值的。那么,如何使值类型的数据作为方法参数时传递的也是引用呢?

方法很简单,只需要在形参的数据类型前加上关键字ref,并在调用时相应地实参前也加上关键字ref即可。

例如:  void  Swap( ref String first, ref String second)   {   .......}

String a="dddd",b="dbbb";

Swap(ref a,ref b); 注意:ref参数必须是可以赋值的变量

2、输出参数---out

      除了将参数单向传入一个方法(传值),或同时将参数传入和传出一个方法(传引用)之外,还可以将数据从一个方法内部单向传出方法。为此,代码需要使用关键字out来修饰参数类型。

例如:  int x;   //

func(out x);     //out参数必须是可以赋值的变量,在调用func方法前对out参数赋不赋值都可以。

void func(out int x ) {};// 在此方法中,在使用out参数x之前必须对其赋值,即使在调用此方法前已经对out参数x赋值了,在此方法中仍吧x看做未赋值的变量。

ref参数与out参数都是传引用,在方法中对参数所做的修改都会传到调用者。区别在于,out参数不接受调用者传来参数的数据值,而是把该参数当做未赋值的参数。

 3、参数数组-----params(可以将相同类型,数量可变的多个参数传给一个方法)

引入:一般,参数的数量都是由目标方法声明所确定。然而,有时我们希望参数的数量是可变的。或许最好的方法是为方法传一个数组。然而,这会使调用代码变得稍微复杂一些,因为需要事先构造一个数组,再将这个数组作为参数来传递。 为了简化代码,c#提供了一个特殊的关键字,它允许在调用一个方法是提供数量可变的参数,而不是由方法事先固定好参数的数量。

示例:

运行结果:

示例说明:上述例子中方法func可接受数量可变的参数,不管这些参数是以逗号分隔的,还是作为一个数组来传递的。为了获得这样的效果,func方法需要:(1)在方法声明的最后一个参数之前,添加一个parmas关键字。(2)将最后一个参数声明为一个数组。

注意事项:

@1、参数数组不一定是方法声明中的唯一参数。单数必须是最后一个参数。由于只有最后一个参数才可能是参数数组,所以方法最多只能有一个参数数组。

@2、调用者可以为参数数组指定0个参数,这会造成包含0个数据项的一个数组。也可以显示地使用一个数组,而不是以逗号分隔的参数列表,最终生成的CIL代码是一样的。

@3、参数数组是类型安全的------类型必须匹配与数组指定的类型。

@4、假如目标方法的实现要求一个最起码的参数数量,请在方法声明中显示指定必须提供的参数。这样一来,假如要求的参数遗失了,就会导致编译器报错,而不需要依赖于运行时错误处理。例如:使用int max (int first,params int[] operands)而不是int max(params int[] operands),确保至少有一个值传给方法max。

4、可选参数:

    从c#4.0开始,增添了对可选参数的支持。声明方法是将常量赋给参数,以后调用方法是就不必每一个参数都指定,若不指定该参数则该参数为方法声明时指定的初始值。

例如:

void  func(int x, int y=2) { Console.WrinteLine(x+y);}

func(3,2) 和func(3)的输出结果是相同的。

注意:

@1、可选参数一定放在所有必须的参数(没有默认值的参数)后面。可选参数的数量可以是多个。

@2、默认值必须是一个常量,或者说必须是编译时能确定的一个值。

5、命名参数

   命名参数是c#4.0新增的一个方法调用功能。利用命名参数,调用者可显示指定参数名,并为该参数赋一个值而不是像以前那样只能依据参数顺序来决定哪个值赋给哪个参数。

例如: void  func(int x, int y=2) { Console.WrinteLine(x+y);}     func(y:3,x:2);

void  display(string firstname, string middlename=default(string), string lastname =default(string));      display(firstname:"susan",lastname: "lili");

注意:如果一个方法有大量参数,而且其中许多都是可选参数(访问Microsoft COM库时,这是很常见的情况),那么命名参数语法肯定能带来不少便利。但这个便利的代价是牺牲方法接口的灵活性。过去,参数名可以自由更改,不会造成调用代码无法编译。但在添加了命名参数后,参数名就成为方法接口的一部分。更改名称会导致使用命名参数的代码无法编译。

6、方法解析(即当同一个方法调用可以适用多个方法,将调用哪个方法)

    当同时使用参数数组,可选参数,命名参数,方法重载等功能时,可能造成同一个方法调用可以适用多个方法。

(1)假如由于一个方法有一个可选参数,造成两个方法都适用(方法重载时可能出现),编译器最终选择的将使无可选参数的方法。

(2)假如有两个适用的方法,每个都需要(对参数)执行一次隐式转换,就选择与更具体的类型匹配的方法。例如,如果调用者传递的是一个int,那么接受double的方法将优先于接受object的方法。这是由于double比object更具体。

(3)如果有多个适用的方法,但无法从中挑选一个最具唯一性的,编译器就会报错,指明调用存在歧义。

c# 方法参数(传值,传引用,ref,out,params,可选参数,命名参数)的更多相关文章

  1. Dart 知识点:位置参数(必选)、位置参数(可选)、命名参数(都是可选)

    先后顺序:位置参数(必选).位置参数(可选).命名参数(都是可选) 位置参数(可选).命名参数(都是可选),不能同时使用

  2. C# 传值和传引用 ( ref out in )

    引用类型的变量不直接包含其数据:它包含的是对其数据的引用.当通过值传递引用类型的参数时,有可能更改引用所指向的数据,如某类成员的值(更改属性的值),但是无法更改引用本身的值:也就是说,不能使用相同的引 ...

  3. js中 函数参数的 传值/传引用 问题

    如果  传入function的参数是  (数值.字符串.布尔值) 此时是以 传值 的方式 进行. 如果  传入function的参数是  (数组.对象.其他函数) 此时是以 传引用 的方式 进行. 1

  4. Python参数传递(传值&传引用)

    # 测试参数是传值还是传引用def test(arg): print("test before") print(id(arg)) arg[1]=30 # 测试可变对象 # arg[ ...

  5. C#方法中三个重要的参数:out、ref、params

    备注:适用于初学者,自学于传智播客. 1.out参数. 概念:如果在一个方法中,返回多个相同类型值的时候,可以考虑返回一数组.但是返回多个不同类型值的时候,返回数组显然不能解决问题,这时就引入out参 ...

  6. Java方法中传值和引用传递的问题(转)

    说明:标题其实说法是错误的.Java中只有值传递,没有引用传递. ... ... //定义了一个改变参数值的函数 public static void changeValue(int x) { x = ...

  7. 【Unity|C#】基础篇(4)——函数参数类型(值参/ref/out/params)

    [学习资料] <C#图解教程>(第5章):https://www.cnblogs.com/moonache/p/7687551.html 电子书下载:https://pan.baidu.c ...

  8. Python中参数是传值,还是传引用?

    在 C/C++ 中,传值和传引用是函数参数传递的两种方式,在Python中参数是如何传递的?回答这个问题前,不如先来看两段代码. 代码段1: def foo(arg): arg = 2 print(a ...

  9. Python 函数中,参数是传值,还是传引用?

    在 C/C++ 中,传值和传引用是函数参数传递的两种方式,在Python中参数是如何传递的?回答这个问题前,不如先来看两段代码. 代码段1: def foo(arg): arg = 2 print(a ...

随机推荐

  1. QS之warning message

    Multiple message categories are specified as a comma separated list.

  2. 使用arm开发板搭建无线mesh网络(二)

    上篇博文介绍了无线mesh网络和adhoc网络的区别,这篇文章将介绍无线mesh网络的骨干网节点的组建过程.首先需要介绍下骨干网节点的设计方案:每个骨干网节点都是由一块友善之臂的tiny6410 ar ...

  3. 开始使用Ambari吧

    最开始接触Hadoop是研究生入学后,帮师姐装装集群什么的.过程很繁琐,很重复,很是让人抓狂.当时装一个三台机器的集群需要两天左右,这还是装的很熟练的时间花费,刚入手的时候简直是惨不忍睹,三台机器装了 ...

  4. 可迭代的集合类型使用foreach语句

    在学习算法这本书图论那一部分的时候,接触到了几个类似for(int w:G.adj(v)),的语句,不是很理解,就去百度,发现这是一种叫做foreach的语法,在书的76页有讲到,但是之前没认真看书, ...

  5. Model&Animation

    [Model&Animation] 1.FBX文件是一个完整的模型,通常内含Mesh,Material,Texture,Animation,即内含构成一个完成GameObject所需要的一切组 ...

  6. WIN7 WIN8 笔记本无线网卡MAC地址修改

    找了好久,尝试了好多种方法,最后终于在下面的网址里找到了解决方案 http://jingyan.baidu.com/article/ceb9fb10e32bce8cac2ba04a.html 使用MA ...

  7. LeetCode100:Same Tree

    Given two binary trees, write a function to check if they are equal or not. Two binary trees are con ...

  8. C# 抽象类和接口的区别

    从表象上来说,抽象类可以给出一些成员的实现,而接口却不包含成员的实现,抽象类的成员可以被继承类来部分实现,而接口类中的成员要子类来全部实现 .还有一个类可以实现多个接口,但只可以继承一个抽象类,这只是 ...

  9. IAP内购

    IAPHelper.h // // IAPHelper.h // airplay // // Created by apple on 13-10-23. // Copyright (c) 2013年 ...

  10. java设计模式(装饰模式)

    装饰模式实现了可以动态地为原对象扩展方法 装饰对象与被装饰的都实现了同一个接口(或抽象类) 举个例子: 工作 可以边吃东西边工作,也可以边喝东西边工作,还可以工作的时候边吃边喝 创建共同接口 Work ...