C#参数详解
参数
可选参数与命名参数
设计方法时,我们可以为部分参数设置默认值,在方法调用时就可以不提供该参数,使用其默认值。此外,调用方法时可以通过指定参数名的方式来传递参数。话不多说,请看以下示例:
static void Main(string[] args)
{
SomeMethod(); //X=0,Y=0,Z=0
SomeMethod(y: 5, z: 10); //X=0,Y=5,Z=10
Console.ReadLine();
}
private static void SomeMethod(int x = 0, int y = 0, int z = 0)
{
Console.WriteLine($"X={x},Y={y},Z={z}");
}
上述SomeMethod方法,接受Int类型参数x、y、z,并设置默认值0。第1次调用时没有指定参数,C#编译器自动嵌入参数的默认值。第2次则为y和z参数显示指定了要传递的值。
可选参数的使用规则
- 有默认值的参数必须放在没有参数值的所有参数之后。
- 默认值必须是编译时能确定的常量值(例如不能将参数的默认值设置为DateTime.Now)。
- 不能重命名参数变量。
- 更改参数的默认值具有潜在的危险性(调用该方法可能产生意料之外的结果)。
- 如果参数使用ref或out关键字标识,就不能设置默认值。
以传递引用的方式传递参数
在方法中,参数是值类型还是引用类型,两种情况下的处理方式有着明显的不同。
static void Main(string[] args)
{
int i = 0;
GetVal(i);
Console.WriteLine(i); //0
int[] arr = new int[] { 0 };
GetVal(arr);
Console.WriteLine(arr[0].ToString()); //10
Console.ReadLine();
}
private static void GetVal(int p_Int)
{
p_Int = 10;
}
private static void GetVal(int[] p_Arr)
{
p_Arr[0] = 10;
}
对于值类型实例,传递给方法的是实例的一个副本,方法中对这个副本的操作不影响调用者中的实例;对于引用类型实例,传递给方法的是实例对象的引用(或者说指向对象的指针)。CLR允许以传引用而非传值的方式传递参数,在C#中,使用out或ref关键字实现此功能。
out和ref关键字的区别
使用ref关键字时,调用方法前必须初始化参数的值,被调用的方法可以对该值进行读取或写入;使用out关键字时,在调用方法之前可以不进行初始化,必须在方法中进行初始化。
如下,向GetVal传递未经初始化的参数str2时,无法通过编译。
static void Main(string[] args)
{
string str = "before Porcess";
GetVal(ref str);
Console.WriteLine(str);
string str2;
GetVal(ref str2); //Error:Use of unassigned local variable 'str2'
Console.WriteLine(str2);
Console.ReadLine();
}
private static void GetVal(ref string p_Str)
{
p_Str = "Processed";
}
修改上述GetVal方法,在方法内部不对参数进行初始化,依旧无法通过编译。
//Error:The out parameter 'p_Str' must be assigned to before control leaves the current method
private static void GetVal(out string p_Str)
{
string anotherStr = "Processed";
}
值类型使用out和ref
static void Main(string[] args)
{
int i = 0;
GetVal(ref i);
Console.WriteLine(i); //10
Console.ReadLine();
}
private static void GetVal(ref int p_Int)
{
p_Int = 10;
}
上述代码,使用ref关键字,将变量i的地址传递给GetVal,p_Int是一个指针,指向Main栈帧中的i的值。在GetVal方法内部,p_Int指向的值被修改为10。
引用类型使用out和ref
static void Main(string[] args)
{
int[] arr = new int[] { 0 };
GetVal(arr);
//GetVal(ref arr);
Console.WriteLine(arr[0].ToString()); //0
Console.ReadLine();
}
private static void GetVal(int[] p_Arr)
//private static void GetVal(ref int[] p_Arr)
{
p_Arr = new int[] { 0 };
p_Arr[0] = 10;
}
这段代码输出的结果是0,和本节开头为方法传递数组的示例输出结果不太相同。差别仅为在方法中构造了一个新的对象,从输出结果可以看出,新对象的指针并没有返回给调用者。为了将新对象返回给调用者,可以使用out和ref关键字(注释掉的部分)。
注意:以传递引用的方式传给方法变量时,参数类型必须与方法签名中声明的类型完全一致。
可变数量参数
方法有时需要获取可变数量的参数,使用params关键字,使方法能够接受可变数量的参数。
static void Main(string[] args)
{
int i = Add(1, 2, 3, 4, 5, 6, 7, 8, 9);
Console.WriteLine(i);
Console.ReadLine();
}
private static int Add(params int[] p_Arr)
{
int sum = 0;
for (int i = 0; i < p_Arr.Length; i++)
{
sum += p_Arr[i];
}
return sum;
}
使用params关键字时,编译器会向参数应用定制特性System.ParamArrayAttribute的一个实例。
执行步骤:
- 当C#编译器检测到方法调用时,会首先检查所有具有指定名称、同时参数没有应用ParamArray特性的方法。
- 如果找到匹配的方法,就生成调用的代码。
- 如果没有找到,就接着检查应用了ParamArray特性的方法。
- 找到匹配的方法,编译器先生成代码构造一个数组,填充元素,再生成代码来调用所选的方法。
C#参数详解的更多相关文章
- Nginx主配置参数详解,Nginx配置网站
1.Niginx主配置文件参数详解 a.上面博客说了在Linux中安装nginx.博文地址为:http://www.cnblogs.com/hanyinglong/p/5102141.html b.当 ...
- iptables参数详解
iptables参数详解 搬运工:尹正杰 注:此片文章来源于linux社区. Iptalbes 是用来设置.维护和检查Linux内核的IP包过滤规则的. 可以定义不同的表,每个表都包含几个内部的链,也 ...
- chattr的常用参数详解
chattr的常用参数详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在实际生产环境中,有的运维工程师不得不和开发和测试打交道,在我们公司最常见的就是部署接口.每天每个人部署的 ...
- mha配置参数详解
mha配置参数详解: 参数名字 是否必须 参数作用域 默认值 示例 hostname Yes Local Only - hostname=mysql_server1, hostname=192.168 ...
- $.ajax()方法所有参数详解;$.get(),$.post(),$.getJSON(),$.ajax()详解
[一]$.ajax()所有参数详解 url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址. type: 要求为String类型的参数,请求方式(post或get)默认为get.注 ...
- linux PHP 编译安装参数详解
linux PHP 编译安装参数详解 ./configure --prefix=/usr/local/php --with-config-file-path=/usr/local/php/etc -- ...
- 【转】jqGrid 各种参数 详解
[原文]http://www.cnblogs.com/younggun/archive/2012/08/27/2657922.htmljqGrid 各种参数 详解 JQGrid JQGrid是一个 ...
- HTML滚动字幕代码参数详解及Js间隔滚动代码
html文字滚动代码 <marquee style="WIDTH: 388px; HEIGHT: 200px" scrollamount="2" dire ...
- mysql5.6主从参数详解
mysql5.6的主从相当的不错,增加了不少参数,提升了主从同步的安全和效率,以下是mysql5.6主从参数详解. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ...
- Linux 之 编译器 gcc/g++参数详解
2016年12月9日16:48:53 ----------------------------- 内容目录: [介绍] gcc and g++分别是gnu的c & c++编译器 gcc/g++ ...
随机推荐
- C#使用Xamarin开发可移植移动应用进阶篇(6.使用渲染器针对单个平台自定义控件..很很很很重要..),附源码
前言 系列目录 C#使用Xamarin开发可移植移动应用目录 源码地址:https://github.com/l2999019/DemoApp 可以Star一下,随意 - - 说点什么.. 本篇..基 ...
- Cause: net.sf.cglib.beans.BulkBeanException; nested exception is com.ibatis.common.jdbc.exception.NestedSQLException:
2017-03-13 15:40:15,003 ERROR [com.hisense.hitv.service.dotexc.impl.DotExcPolicyServiceImpl.updateD ...
- AOP 面向切面的编程
一.面向切面的编程需求的产生 代码混乱:越来越多的非业务需求(日志和验证等)加入后,原有的业务方法急剧膨胀.每个方法在处理核心逻辑的同时还必须兼顾其他多个关注点. 代码分散: 以日志需求为例,只是为了 ...
- Spring MVC 中获取session的几种方法
Spring MVC 中使用session是一种常见的操作,但是大家上网搜索一下可以看到获取session的方式方法五花八门,最近,自己终结了一下,将获取session的方法记录下来,以便大家共同学习 ...
- 安装Hadoop 2.7.3的过程中遇到的一些问题及解决方法。
1. 启动hadoop 时发现namenode 没有启动起来 出现以下错误: Incorrect configuration: namenode address dfs.namenode.servic ...
- JAVA奇技淫巧简化代码之lombok
背景 最近在做一个小功能,又不想在原有体态臃肿的项目中追加,为了调试方便并且可以快速开发就采用了springboot.由于使用了JPA,建了几个类,然后通过IDE去生成其属性的构造器.getter.s ...
- 打印1到最大的n位数-Java
在练习剑指offer的时候,第12题打印1到最大的n位数的时候,想找个java版的,但大家要么用BigInteger做,要么给出其他的方法.我觉得要给就给最好的方法,下面是我自己参考C++代码写的ja ...
- PKIX path building failed
百度这个问题,很多人都说是证书问题.至于是什么证书呢?搞了老半天原来是 /Java/jre/lib/security/cacerts不正确.换了个jdk版本就解决这个问题了. 可靠的jdk1.8下载链 ...
- ctf常见php弱类型分析
1. 布尔反序列化 $unserialize_str = $_POST['password']; $data_unserialize = unserialize($unserialize_str); ...
- 《Java从入门到放弃》JavaSE入门篇:面向对象语法二(入门版)
想了半天,发现单独的封装和多态没什么好讲的,我们就简单说说Java里面对应的语法吧. 相关内容如下: 一.访问修饰符 二.getter/setter方法 三.构造方法 四.super和this 五.s ...