1、原来函数这样传参数组
先看一个函数和函数调用。 ide
static void Main(string[] args) { int num = 10; Test(num);//局部变量在使用以前赋值 //Test(10); //直接为局部变量赋值 } static void Test(int i)//i 至关于一个局部变量 { i++; }
Test函数定义了一个int 类型的变量i做为参数,这个地方至关于声明了一个局部变量,而局部变量使用以前必须赋值,这就是为何函数使用的时候要赋值(传一个值进去)。函数
假如不想给参数赋值怎么办?那就在函数声明参数的时候给参数(局部变量)赋值,这样调用函数的时候就能够不给参数传值。以下:spa
static void Main(string[] args) { int x= Test();//能够不传值 int y= Test(20);//也能够传值 Console.WriteLine(x); Console.WriteLine(y); Console.Read(); } static int Test(int i=10)//为局部变量赋值,传参数的时候能够不为i赋值 { i++; return i; }
注意:赋初值的参数必须放在参数列表最右侧,能够有多个带初值的参数。code
做用:为参数赋了初值,在调用的时候能够赋值也能够不赋值,做用是为参数指定默认值,。orm
static void Test(int a,int b=20, int i=10) { //to do }
在为方法传参数的时候必须按照参数声明的顺序传,这个一直是这样作的,也没多想过,其实也能够不按照传参的顺序,以下:blog
static void Main(string[] args) { Test2(s:"hello",b:true ,i:10); //请看这个地方 Console.Read(); } static void Test2(int i,string s,bool b) { Console.WriteLine(i); Console.WriteLine(s); Console.WriteLine(b); }
传参的时候指定哪一个参数传什么值就能够不按照顺序传参,这个不是很经常使用,可是之前不知道,又长见识了。内存
补充:评论你有人问,若是有重载怎么办,这个问题,问得很是好。先看一下下面的代码get
static void Main(string[] args) { int x = Test(10); int y = Test(20,30); int z = Test(10, 20, 30); Console.WriteLine(x);//输出10 Console.WriteLine(y);//输出50 Console.WriteLine(z);//输出60 Console.Read(); } static int Test(int i ) { return i; } static int Test(int a,int b=20) { return a + b; } static int Test(int a,int b=20,int c=30) { return a + b + c; }
当有重载的时候,不给带有默认值参数赋值,他会优先执行,不带默认参数的函数。string
2、params 参数数组(可变参数)
咱们知道数组的长度是不可变的。当咱们把一个数组做为参数传递的时候,想改变数组长度不是一件容易的事儿。params 参数数组就能够随便指定参数长度,也不用在传参的时候去特地定义一个数组传参。使用很是方便。
例:
static void Main(string[] args) { int[] arr = new int[]{1,2,4,5,6}; Test1(arr); Console.WriteLine(); Test2(1,2,4,56,78,8,4); Console.WriteLine(); Test2(1,5,7); Console.Read(); } static void Test1(int [] arr ) { for (int i = 0; i < arr .Length ; i++) { Console.Write(arr [i]+" "); } } static void Test2(params int[] arr) //params 数组 { for (int i = 0; i < arr.Length; i++) { Console.Write(arr [i]+" "); } }
params 参数数组,做为参数的时候,参数个数是可变的,固然也能够为0,可是用params 参数数组的时候,一个函数里只有一个params参数,而且必须放在参数列表的最后。
params用法: 一、用来修饰方法的参数,并且只能修饰一维数组;
二、一个方法只能出现一个params参数,而且必须把params参数数组放在最后,不能带有默认值;
三、调用方法的时候,params修饰的参数,能够传一个数组,也能够传数组的元素,也能够什么都不传(长度就为0);
在控制台应用程序中,如Console.WriteLine("我叫{0},今年{1}岁,喜欢{2}","Vivu","22","C#");其实就用到了params参数,这个重载就是:
console.WriteLine(string.Format,Params string[] arr);
总结:params 参数修饰的数组至关于长度可变的参数数组。它是修饰参数(一维数组)的一个关键字。用处就是在不知道参数个数或参数个数有可能发生变化的状况下使用。
3、ref和out参数修饰符
ref:
值类型在传递值的时候,只是复制了一份值赋给另外一个变量,另外一个变量改变并不能改变原有的值。例如:
int num = 200; int a = num; a -= 100; Console.WriteLine(num);//输出200 Console.WriteLine(a);//输出100
可是,假如num表明我钱包里的钱,我把钱包交给别人(int a=num),别人用了100(a-=100),这时候,我钱包里的钱(num)应该是多少?按照上面的方式执行就会出错,钱包里的钱是不会变的,由于在传值的时候只是复制了num的一份值给a,a改变并不会改变num的值。那该怎么办???
若是我传递的值是num的引用(能够理解为地址),那么a 改变了num就也会改变了。可是int 类型是值传递,怎么办,把它变为引用就要用到ref和out参数。
ref和out参数的做用就是把值传递改成引用传递。
改写上面的钱包的例子。
static void Main(string[] args) { int num = 200; int res =Test(ref num ); Console.WriteLine(num );//输出100 Console.WriteLine(res );//输出100 Console.Read(); } static int Test(ref int a) { a -= 100; return a; }
在内存图中分析一下ref参数:
ref参数能够按引用类型传递,若是ref修饰的是引用类型的参数呢?先看下面的例子:
先建立一个person类
private int _age; private string _name; public string Name { get { return _name; } set { _name = value; } } public int Age { get { return _age; } set { _age = value; } }
再看一下面ref修饰引用类型的状况。
static void Main(string[] args) { Person p = new Person() { Name ="红红"}; Test1(p); Console.WriteLine(p.Name); //输出什么??? TestRef1(ref p); Console.WriteLine(p.Name); //输出什么??? Test2(p); Console.WriteLine(p.Name); //输出什么??? TestRef2(ref p); Console.WriteLine(p.Name); //输出什么??? Console.Read(); } static void Test1(Person p) { p = new Person() { Name = "绿绿" }; } static void TestRef1(ref Person p) { p = new Person() { Name ="蓝蓝"}; } static void Test2(Person p) { p.Name = "嘿嘿"; } static void TestRef2(ref Person p) { p.Name = "掰掰"; }
输出结果是,红红,蓝蓝,嘿嘿,掰掰。画一下内存图很好分析。引用类型原本传递的就是地址,因此引用类型使用ref参数和不使用是同样的。这里偷一下懒,想知道的去运行,画一下内存图吧!!!
ref用法:一、使用ref必须在参数声明和调用的时候都带上ref关键字;
二、只能修饰变量,不能修饰常量;
三、ref在方法中能够对ref修饰的值不改变,可是在传参前必须给参数赋值;
out:
ref 在使用以前必须赋初始值,它主要侧重于改变,修改值。使用ref,在函数声明与调用的时候必须在参数前面加上ref。out参数的做用与使用方法与ref相似,与ref不一样的是out在使用前没必要赋初始值,但在返回的时候必须为他赋值,因此out主要侧重于输出。out修饰符参数例子:
static void Main(string[] args) { int num = 200; int b; int a = TestOut(200,out b); Console.WriteLine(a);//输出100 Console.WriteLine(b);//输出200 Console.Read(); } static int TestOut(int a,out int b) { b = a; a -= 100; return a; }
总结:ref和out参数修饰符,都是把参数按引用类型传递,可是ref侧重于改变值,而out侧重于输出。一个函数只有一个输出值,但想返回多个值的时候就用out参数修饰符。
ref在使用以前必须赋值,out在返回以前必须赋值。ref和out在函数使用和调用的时候,参数前面必须加ref和out参数。