C#中ref、out类型参数的区别和params类型参数的用法

时间:2022-05-12 21:35:25

欢迎大家访问我的blog:http://www.ybloy.com

给大家讲一个故事:

话说古时候,在一个名字叫C#的繁华的大城市里面,有两家珠宝加工店,一家叫ref,另外一家叫out

有一天,有名字叫ab的两个人每人都各带了一公斤黄金要加工首饰。

a去了ref店,ref的掌柜告诉a说,请客官稍等,我们加工的速度是很快的,大概就一个小时左右吧。a说,我敢时间呢,能不能用我的黄金换现成的首饰。ref老板说,客官,实在是对不起,本店只为客人加工,我们没有这样的服务。如果您敢时间的话,我推荐您去out店,他们专门做这样的业务。

b去了out店,说,掌柜的,你必须要用我的这一公斤黄金给我加工首饰。out店的掌柜不好意思的笑了笑,客官实在是对不起我们这里只用黄金交换加工好了的首饰。我们不提供加工的服务,你可以去ref店,他们专门做这样的业务。

就这样,两家店各做各的,都说同行是冤家。两个店却关系很好。业务都蒸蒸向上。

两家店都相安无事的过了很多年。突然城东开了一家名叫params的店。这家什么都加工,不管是黄金珠宝还是黑土白云。不过由于不太专业,光顾的客人不怎么多。

(故事而已,如有雷同。纯属娱乐。)

 

示例代码:

 1  using  System;
 2  using  System.Collections.Generic;
 3  using  System.Linq;
 4  using  System.Text;
 5 
 6  namespace  RefDifferenceToOut
 7  {
 8       class  Program
 9      {
10           static   void  Main( string [] args)
11          {
12               // 这里做为ref类型的参数必须初始化。ref类型参数传入未初始化变量会报错。
13               string  refTestStr  =   string .Empty;
14 
15               // 作为out类型参数可以不初始化,因为out类型参数是在函数内部赋值。
16               string  outTestStr  =   string .Empty;
17              
18              Program p  =   new  Program();
19             
20              Console.WriteLine( " 默认空值输出: " );
21              Console.WriteLine(p.UseRef( ref  refTestStr));
22              Console.WriteLine(p.UseOut( out  outTestStr));
23              Console.WriteLine( " refTestStr: "   +  refTestStr);
24              Console.WriteLine( " outTestStr: "   +  outTestStr);
25              Console.WriteLine( " ------------------- " );
26 
27              refTestStr  =   " 1 " ;
28              outTestStr  =   " 2 " ;
29 
30              Console.WriteLine( " 从新赋值:refTestStr = \ " 1 \ " ;outTestStr = \ " 2 \ " ; " );
31              Console.WriteLine(p.UseRef( ref  refTestStr));
32              Console.WriteLine(p.UseOut( out  outTestStr));
33              Console.WriteLine( " refTestStr: "   +  refTestStr);
34              Console.WriteLine( " outTestStr: "   +  outTestStr);
35              Console.WriteLine( " ------------------- " );
36 
37 
38              refTestStr  =   " 3 " ;
39              outTestStr  =   " 4 " ;
40              Console.WriteLine( " 从新赋值:refTestStr = \ " 3 \ " ;outTestStr = \ " 4 \ " ; " );
41              Console.WriteLine(p.UseRef( ref  refTestStr));
42              Console.WriteLine(p.UseOut( out  outTestStr));
43              Console.WriteLine( " refTestStr: "   +  refTestStr);
44              Console.WriteLine( " outTestStr: "   +  outTestStr);
45              Console.WriteLine( " ------------------- " );
46 
47 
48              Console.WriteLine( " --------params------- " );
49              p.param( " str_a " " 2 " " 3 " " 4 " );
50 
51 
52          }
53 
54           public   string  UseRef( ref   string  refTest)
55          {
56               return  refTest  +=   " rrrrrref " ;
57          }
58 
59           public   string  UseOut( out   string  outTestStr)
60          {
61               // 在这里需要给outTest从新赋值
62              outTestStr  =   " 0 " ;
63              outTestStr  +=   " oooooout " ;
64               return  outTestStr;
65          }
66 
67           ///   <summary>
68           ///  params参数练习。
69           ///   </summary>
70           ///   <param name="a"> 同是string参数 </param>
71           ///   <param name="list"> string 类型列表参数 </param>
72           public   void  param( string  a, params   string [] list)
73          {
74              Console.WriteLine(list.ToString());
75 
76               int  i  =   0 ;
77 
78              Console.WriteLine(a);
79               foreach  ( string  s  in  list)
80              {
81                  Console.WriteLine(i ++   + " _ " +  s);
82              }
83          }
84      }
85  }
86 

 

 

输出结果:

默认空值输出:

rrrrrref

0oooooout

refTestStr:rrrrrref

outTestStr:0oooooout

-------------------

从新赋值:refTestStr = "1";outTestStr = "2";

1rrrrrref

0oooooout

refTestStr:1rrrrrref

outTestStr:0oooooout

-------------------

从新赋值:refTestStr = "3";outTestStr = "4";

3rrrrrref

0oooooout

refTestStr:3rrrrrref

outTestStr:0oooooout

-------------------

--------params-------

System.String[]

str_a

0_2

1_3

2_4

 

 

总结:

refout都对函数参数采用引用传递形式——不管是值类型参数还是引用类型参数,并且定义函数和调用函数时都必须显示生命该参数为ref/out形式。两者都可以使函数传回多个结果。

两者区别:

两种参数类型的设计思想不同,ref的目的在于将值类型参数当作引用型参数传递到函数,是函数的输入参数,并且在函数内部的任何改变也都将影响函数外部该参数的值;而out的目的在于获取函数的返回值,是输出参数,由函数内部计算得到的值再回传到函数外部,因此必须在函数内部对该参数赋值,这将冲掉函数外部的任何赋值,使得函数外部赋值毫无意义。

表现为:

1out必须在函数体内初始化,这使得在外面初始化变得没意义。也就是说,out型的参数在函数体内不能得到外面传进来的初始值。
2
ref必须在函数体外初始化。
3
、两者在函数体内的任何修改都将影响到函数体外面。