参数传递
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了参数传递相关的知识,希望对你有一定的参考价值。
参数传递
当调用带有参数的方法时,您需要向方法传递参数。
- 值传递参数:这种方式复制参数的实际值给函数的形式参数,实参和形参使用的是两个不同内存中的值。在这种情况下,当形参的值发生改变时,不会影响实参的值,从而保证了实参数据的安全。
using System;
namespace CodeReview
{
class Program
{
static void Main(string[] args)
{
int a = 0;
int b = 1;
Console.WriteLine("在交换之前,a 的值: {0}", a);
Console.WriteLine("在交换之前,b 的值: {0}", b);
Exchange(a, b);
Console.WriteLine("在交换之前,a 的值: {0}", a);
Console.WriteLine("在交换之前,b 的值: {0}", b);
//即使在函数内改变了值,值也没有发生任何的变化。
Console.ReadKey();
}
static void Exchange(int x, int y)
{
int temp;
temp = x;
x = y;
y = temp;
}
}
}
- 引用传递参数:这种方式复制参数的内存位置的引用给形式参数。这意味着,当形参的值发生改变时,同时也改变实参的值(ref/out)
using System;
namespace CodeReview
{
class Program
{
/// <summary>
/// ref 关键字使参数按引用传递.其效果是,当控制权传递回调用方法时,在方法中对参数所做的任何更改都将反映在该变量中 若要使用 ref 参数,方法定义和调用方法都必须显式使用 ref 关键字。
/// out 关键字会导致参数通过引用来传递.这与 ref 关键字类似,不同之处在于 ref 要求变量必须在传递之前进行初始化 若要使用 out 参数,方法定义和调用方法都必须显式使用 out 关键字。
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
int[] arr = { 1, 2, 3, 5, 67, 7 };
float r_avg = 0;
int r_max = 0;
int r_min = 0;
int r_sum = GetIntResultRef(arr, ref r_avg, ref r_max, ref r_min);//ref参数使用之前必须初始化
Console.WriteLine("Ref:Sum:{0},Max:{1},Min:{2},Avg:{3}", r_sum, r_max, r_min, r_avg);
float o_avg;//out参数不需要初始化
int o_max;
int o_min;
int o_sum = GetIntResultOut(arr, out o_avg, out o_max, out o_min);//out参数使用之前必须初始化
Console.WriteLine("Out:Sum:{0},Max:{1},Min:{2},Avg:{3}", o_sum, o_max, o_min, o_avg);
Console.ReadKey();
}
/// <summary>
/// 案例:定义一个方法,求一个整数数组中的总和/最大值/最小值/平均数.如果是一个方法只能有一个返回值,那只能每一个都得定义一个方法来实现,不过有了ref和out这实现起来就方便多了。
/// </summary>
/// <returns></returns>
static int GetIntResultRef(int[] arr, ref float avg, ref int max, ref int min)
{
int sum = 0;
max = arr[0];
min = arr[0];
for (int i = 0; i < arr.Length; i++)
{
sum += arr[i];
if (max < arr[i])
{
max = arr[i];
}
if (min > arr[i])
{
min = arr[i];
}
}
avg = sum / arr.Length;
return sum;
}
static int GetIntResultOut(int[] arr, out float avg, out int max, out int min)
{
int sum = 0;
max = arr[0];
min = arr[0];
for (int i = 0; i < arr.Length; i++)
{
sum += arr[i];
if (max < arr[i])
{
max = arr[i];
}
if (min > arr[i])
{
min = arr[i];
}
}
avg = sum / arr.Length;
return sum;
}
}
}
C#中除非显式指定,否则:所有值类型默认都通过值来传递,所有引用类型都通过引用传递
ref和out都是用来显式将值类型通过引用传递的关键字
using System;namespace CodeReview { /// <summary> /// C#中除非显式指定,否则:所有值类型默认都通过值来传递,所有引用类型都通过引用传递 /// ref和out都是用来显式将值类型通过引用传递的关键字 /// </summary> class Program { static void Main(string[] args) { Console.WriteLine("***********值类型参数***********"); Console.WriteLine("****初始化****"); int i = 1;//int是值类型,按值传递 Console.WriteLine(i); UpdateInt(i); Console.WriteLine("****更新后****"); Console.WriteLine(i); Console.WriteLine("***********引用类型参数***********"); Console.WriteLine("****初始化****"); string[] srr = { "1", "2" };//数组是引用类型,按引用传递 foreach (var s in srr) { Console.WriteLine(s); } UpdateArrFirst(srr); Console.WriteLine("****更新后****"); foreach (var s in srr) { Console.WriteLine(s); } string str = "1";//string字符串传递(字符串是不可变的,改变一个字符串的值就会创建一个新的字符串) Console.WriteLine("string字符串原始值:{0}", str); UpdateString(str); Console.WriteLine("string字符串修改后的值:{0}", str); Console.ReadKey(); } static void UpdateInt(int i) { i += 10; } static void UpdateArrFirst(string[] arr) { arr[0] = "4"; } static void UpdateString(string str) { str = str + "Two"; } } }
命名参数:参数一般需要按定义的顺序传递给方法,命名参数允许按任意顺序传递。
using System; namespace CodeReview { class Program { static void Main(string[] args) { string name = JoinString("张", "三");//按顺序传递 Console.WriteLine(name); name = JoinString(b: "三", a: "张");//任意顺序传递 Console.WriteLine(name); Console.ReadKey(); } static string JoinString(string a, string b) { return a + b; } } }
可选参数:参数可以是可选的,但是必须为可选参数提供默认值,可选参数必须定义在方法所有参数最后的位置
using System; namespace CodeReview { class Program { static void Main(string[] args) { string name = JoinString("张", "三", "bay");//按顺序传递 Console.WriteLine(name); Console.ReadKey(); } static string JoinString(string a, string b, string c = "hello") { return a + b + c;//其中c为可选参数,如果不传递值就使用默认值 } } }
总结:
ref和out的区别在C# 中,既可以通过值也可以通过引用传递参数。通过引用传递参数允许函数成员更改参数的值,并保持该更改。若要通过引用传递参数, 可使用ref或out关键字。ref和out这两个关键字都能够提供相似的功效,其作用也很像C中的指针变量。它们的区别是:
1、使用ref型参数时,传入的参数必须先被初始化。对out而言,必须在方法中对其完成初始化。
2、使用ref和out时,在方法的参数和执行方法时,都要加ref或out关键字。以满足匹配。
3、out适合用在需要retrun多个返回值的地方,而ref则用在需要被调用的方法修改调用者的引用的时候。
4、字符串是不可变的,修改一个字符串的值就会创建一个新的字符串。
以上是关于参数传递的主要内容,如果未能解决你的问题,请参考以下文章