C#中out、ref、params参数的使用

来源:互联网 发布:淘宝手机单 编辑:程序博客网 时间:2024/06/01 22:58

转载请注明出处:http://blog.csdn.net/hongjiapeng/article/details/78088302


1、out参数。

如果你在一个方法中,返回多个相同类型的值的时候,可以考虑返回一个数组。但是,如果返回多个不同类型的值的时候,返回数组就不行了,那么这个时候,我们可以考虑使用out参数。out参数就侧重于在一个方法中可以返回多个不同类型的值。

不使用out参数,写一个方法 求一个数组中的最大值、最小值、总和、平均值

  static void Main(string[] args)        {            int[] numbers = { 1,2,3,4,5,6,7,8,9,10};            //将要返回的4个值,放到一个数组中返回            int[] result= GetMaxMinSumAvg(numbers);            Console.WriteLine("该数组的最大值为{0},最小值为{1},总和为{2},平均值为{3}",result[0],result[1],result[2],result[3]);            Console.ReadKey();        }        /// <summary>        /// 求一个数组的最大值、最小值、总和、平均值        /// </summary>        /// <param name="nums">要求的数组</param>        static int[] GetMaxMinSumAvg(int[] nums)         {            int[] temp=new int[4];            //假设res[0]为最大值 res[1]为最小值 res[2]为总和 res[3]为平均值            temp[0] = nums[0];//max              temp[1] = nums[0];//min            temp[2] = 0;//sum            temp[3] = 0;//avg            for (int i = 0; i < nums.Length; i++)            {                if (nums[i] > temp[0])                {                    temp[0] = nums[i];                } if (nums[i] < temp[1])                {                    temp[1] = nums[i];                }                temp[2] += nums[i];//总和            }            temp[3] = temp[2] / nums.Length;//平均值            return temp;        }     

计算结果如下:

计算结果


但是这样写有一个问题,上面我们返回的这4个值都是int类型,所以可以放到int类型的数组里面。假如在上面那个GetMaxMinSumAvg(int[] nums)函数里面,我想要你再额外的返回给我一个字符串,该怎么做呢?

...temp[0] = nums[0];//max  temp[1] = nums[0];//mintemp[2] = 0;//sumtemp[3] = 0;//avg//假如还需要返回得调用者一个字符串和一个布尔类型的值(下面两行代码),该怎么做呢?string userName="admin";bool b=true;for (int i = 0; i < nums.Length; i++)...

要返回的多个值是同一种类型可以用数组,但要返回的类型不是一种,该怎么做呢?这就需要用到我们的out参数。
下面再写一个方法

 static void Main(string[] args)        {            int[] numbers = { 1,2,3,4,5,6,7,8,9,10};            int max1;//这里可以只定义、不赋值,因为在调用下面的TestOutPram函数的时候已经给赋了            int min1;            int sum1;            int avg1;            bool b;            string s;            double d;            //上面6个参数的值是从TestOutPram函数多余返回来的,out是多余返回的值            TestOutPram(numbers, out max1, out min1, out sum1, out avg1, out b, out s, out d);            Console.WriteLine("该数组的最大值为{0},最小值为{1},总和为{2},平均值为{3},布尔值为{4},字符串为{5},浮点值为{6}", max1, min1, sum1, avg1, b, s, d);            Console.ReadKey();        }        /// <summary>        /// 计算一个整数数组的最大值、最小值、平均值、总和        /// </summary>        /// <param name="nums">要求值得数组</param>        /// <param name="max">多余返回的最大值</param>        /// <param name="min">多余返回的最小值</param>        /// <param name="sum">多余返回的总和</param>        /// <param name="avg">多余返回的平均值</param>        public static void TestOutPram(int[] nums, out int max, out int min, out int sum, out int avg, out bool b, out string s, out double d)        {            //out参数要求在方法的内部必须为其赋值            max = nums[0];            min = nums[0];            sum = 0;            for (int i = 0; i < nums.Length; i++)            {                if (nums[i] > max)                {                    max = nums[i];                }                if (nums[i] < min)                {                    min = nums[i];                }                sum += nums[i];            }            avg = sum / nums.Length;            b = true;            s = "123";            d = 3.13;        }

使用out参数后,运行结果:
使用out参数后


下面使用out参数做一个简单的登录案例

 static void Main(string[] args)        {            //分别的提示用户输入用户名和密码            //你写一个方法来判断用户输入的是否正确            //返回给用户一个登陆结果,并且还要单独的返回给用户一个登陆信息            //如果用户名错误,除了返回登陆结果之外,还要返回一个 "用户名错误"            //如果用户名错误,除了返回登陆结果之外,还要返回一个 "密码错误"            Console.WriteLine("请输入用户名");            string userName = Console.ReadLine();            Console.WriteLine("请输入密码");            string userPwd = Console.ReadLine();            string msg;            bool b = IsLogin(userName, userPwd, out msg);            Console.WriteLine("登陆结果{0}", b);            Console.WriteLine("登陆信息{0}", msg);            Console.ReadKey();        }        /// <summary>        /// 判断登陆是否成功        /// </summary>        /// <param name="name">用户名</param>        /// <param name="pwd">密码</param>        /// <param name="msg">多余返回的登录信息</param>        /// <returns>返回登录结果</returns>        static bool IsLogin(string name,string pwd,out string msg)         {            if (name=="admin"&&pwd=="123456")            {                msg = "登录成功!";                return true;            }            else if (name=="admin")            {                msg = "密码错误!";                return false;            }            else if(pwd=="123456")            {                msg = "用户米不正确!";                return false;            }            else            {                msg = "未知错误";                return false;            }        }

1、用户名和密码都不正确

这里写图片描述

2、用户名正确,密码都正确

这里写图片描述

3、用户名不正确,密码正确

这里写图片描述

4、用户名、密码都正确

这里写图片描述


下面自己写一个方法,来实现和TryParse函数一样的功能。

 class Program    {                static void Main(string[] args)        {            int num1;//这里没有必要赋初值,num的值是从方法里多余返回的            int num2;            //将字符串转换成int类型,转换后的结果返回布尔类型,将成功或失败后的值 赋值给rusult            bool a = int.TryParse("123a",out num1);                      Console.WriteLine(a);            Console.WriteLine(num1);            bool b = MyTryParse("1244", out num2);            Console.WriteLine(b);                        Console.WriteLine(num2);            Console.ReadKey();        }        /// <summary>        /// 将字符串转Int        /// </summary>        /// <param name="s">要转换的字符串</param>        /// <param name="result">多余返回的值</param>        /// <returns>返回成功或失败</returns>        static bool MyTryParse(string s,out int result)         {             result = 0;             try             {                 result = Convert.ToInt32(s);                 return true;             }             catch              {                 return false;             }        }    }

代码运行结果:
这里写图片描述


2)、ref参数

能够将一个变量带入一个方法中进行改变,改变完成后,再讲改变后的值带出方法。ref参数要求在方法外必须为其赋值,而方法内可以不赋值。


 class Program    {        static void Main(string[] args)        {            //假设小明的月薪为5000            double salary = 5000;            Reward(salary);            Console.WriteLine(salary);            Console.ReadKey();        }        /// <summary>        /// 奖金        /// </summary>        /// <param name="s">薪水</param>        static void Reward(double s)         {            s += 500;        }        /// <summary>        /// 罚款        /// </summary>        /// <param name="s">薪水</param>        static void Fine(double s)        {            s -= 500;        }

上面代码运行后打印的结果:

这里写图片描述


可以看到,月薪还是5000,因为调用的方法无返回值,可以更改下函数返回值类型,然后再调用。但这样感觉还是不是太方便,这时候就可以使用ref参数。

 static void Main(string[] args)        {            //假设小明的月薪为5000            double salary = 5000;            Reward(ref salary);            Console.WriteLine("小明实际月收入为:"+salary);            Console.ReadKey();        }        /// <summary>        /// 奖金        /// </summary>        /// <param name="s">薪水</param>        static void Reward(ref double s)         {            s += 500;        }        /// <summary>        /// 罚款        /// </summary>        /// <param name="s">薪水</param>        static void Fine(double s)        {            s -= 500;        }

这里写图片描述

同样是调用无返回值的函数,加了ref参数后就可以实现想要的结果。


下面做一个练习,使用ref交换两个int类型的变量

 static void Main(string[] args)        {            //使用方法来交换两个int类型的变量            int n1 = 10;            int n2 = 20;            //int temp = n1;            //n1 = n2;            //n2 = temp;            ExchangeVariables(ref n1, ref  n2);            Console.WriteLine(n1);            Console.WriteLine(n2);            Console.ReadKey();            //n1 = n1 - n2;//-10 20            //n2 = n1 + n2;//-10 10            //n1 = n2 - n1;//20 10        }        /// <summary>        /// 交换两个数的值        /// </summary>        /// <param name="n1">变量1</param>        /// <param name="n2">变量2</param>        public static void ExchangeVariables(ref int n1, ref  int n2)        {            int temp = n1;            n1 = n2;            n2 = temp;        }

上面的代码假设ExchangeVariables()函数的参数不加ref的话,打印后的结果肯定还是n1=10,n2=20;加ref参数后,皆可以将n1、n2这两个变量带入一个方法中进行改变,改变完成后,再将改变后的值带出方法给调用者。

这里写图片描述


3)、params可变参数

将实参列表中跟可变参数数组类型一致的元素都当做数组的元素去处理。params可变参数必须是形参列表中的最后一个元素。


下面写一个方法,求一个班级学生的总成绩。

 static void Main(string[] args)        {            int[] s = { 99, 88, 77 };            GetStudentsScores("张三", 10, s);            GetStudentsScores("李四", 11, 100, 100, 100);            Console.ReadKey();        }        /// <summary>        /// 求班级学生的总成绩        /// </summary>        /// <param name="name">姓名</param>        /// <param name="id">学号</param>        /// <param name="score">成绩</param>        public static void GrtStudentsScores(string name, int id, params int[] score)        {            int sum = 0;            for (int i = 0; i < score.Length; i++)            {                sum += score[i];            }            Console.WriteLine("{0}的学号是{1},这次考试的总成绩是{2}", name, id,sum);        }

执行结果:

这里写图片描述


可以看出在主函数里调用GrtStudentsScores函数的时,使用了params参数后,成绩的实参可以传int类型的数组,也可以直接传int类型的变量。但最好是直接传int类型的变量,因为在程序中尽可能的少定义变量,减少内存的负载。


下面使用params参数,求任意数组的和

        static void Main(string[] args)        {                      //求任意长度数组的和 整数类型的            int[] nums = { 1, 2, 3, 4, 5 };            int sum = GetSum(8, 9);            Console.WriteLine("sum="+sum);            Console.ReadKey();        }        public static int GetSum(params int[] n)        {            int sum = 0;            for (int i = 0; i < n.Length; i++)            {                sum += n[i];            }            return sum;        }

运行结果:

这里写图片描述