c#进阶params可变个数的参数

 

目录

1 简单使用

2 可变个数的参数params 的原理

3 性能分析

4 较佳实践建议


  系列索引

C#功能派的进阶2--类型的那些事


1简单使用 

static  Int32 Add( params  Int32[] values) { 
//  NOTE: it is possible to pass the 'values' 
//  array to other methods if you want to. 
Int32 sum  =   0
if  (values  !=   null ) { 
for  (Int32 x  =   0 ; x  <  values.Length; x ++
sum 
+=  values[x]; 

return  sum; 
}

 明显他可以这样使用 

public   static   void  Main() { 
//  Displays "15" 
Console.WriteLine(Add( new  Int32[] {  1 2 3 4 5  } )); 
}

 但是这样有点丑,也许这样会漂亮点。params的特性

public   static   void  Main() { 
//  Displays "15" 
Console.WriteLine(Add( 1 2 3 4 5 )); 
}

      但是哦呼,他真的可以运行。这是params参数的特权,去除params之后就会报错,因为他就变成了3个参数的函数了。是为了消除二义性,将不能再定义不带params 的函数。

2可变个数的参数params 的原理

在想params是如何实现的时候,我猜测params是编译器的语法糖在IL中不存在。打开reflactor来尝试验证

public   static   void  Main() { 
            DisplayTypes(
1 3 4 ); 
            DisplayTypes(
new  Object[] {  1 3 4  }); 
            Console.Read();
        }
private   static   void  DisplayTypes( params  Object[] objects) { 
           
if  (objects  !=   null ) { 
               
foreach  (Object o  in  objects) 
                   Console.WriteLine(o.GetType()); 
           } 
       }

 对应的Main方法

 
 
public   static   void  Main()
{
    
object [] CS$ 0 $ 0000 ;
    DisplayTypes(
new   object [] { ( int 1 , ( int 3 , ( int 4  });
    DisplayTypes(
new   object [] { ( int 1 , ( int 3 , ( int 4  });
    Console.Read();
    
return ;
}

果然不出所料。  

另外补充来自你必须知道的.NET中的分析
param关键字的实质是:param是定制特性ParamArrayAttribute的缩写(关于定制特性的详细论述请参见 第三回:历史纠葛:特性和属性),该特性用于指示编译器的执行过程大概可以简化为:编译器检查到方法调用时,首先调用不包含ParamArrayAttribute特性的方法,如果存在这种方法就施行调用,如果不存在才调用包含ParamArrayAttribute特性的方法,同时应用方法中的元素来填充一个数组,同时将该数组作为参数传入调用的方法体。总之就是param就是提示编译器实现对参数进行数组封装,将可变数目的控制由编译器来完成,                                                  实质是:  void XXXX(  [ParamArrayAttribute] int[] ages){...}

 

3性能分析

其实质其实构造一个 array 在编译时确定其长度来 承载可变个数的参数.但性能上并不划算:因为需要额外构造一个array。

1在堆上分配内存

2初始化其元素

3最后还得被回收。

所以出于性能更好的做法是重载。我们可以看String 中Concat的做法。 

public   sealed   class  String : Object, ... { 
public   static   string  Concat( object  arg0); 
public   static   string  Concat( object  arg0,  object  arg1); 
public   static   string  Concat( object  arg0,  object  arg1,  object  arg2); 
public   static   string  Concat( params   object [] args); 
public   static   string  Concat( string  str0,  string  str1); 
public   static   string  Concat( string  str0,  string  str1,  string  str2); 
public   static   string  Concat( string  str0,  string  str1,  string  str2,  string  str3); 
public   static   string  Concat( params   string [] values); 
}

 

4参数和返回值编写的较好实践:

 

1参数和返回值尽量使用接口和基类

显而易见,可以适用被更多种(派生)类型。

 

2常量性(const-ness)的对象和参数

类的常量性其实是自欺欺人,如前所述(我之前的一篇文章)我们虽然不能改变类的地址,但可以改变地址的值。这样的话C++等实现的常量性类,是在自欺欺人吗?其实我们可以在设计类的时候就不让他改变就得了?(private set),他也有很多不好的地方如 使得执行的时候需要检查是否是常量(不可改变)而降低性能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值