跟小D每日学口语

c#使用params重载方法

一般的方法可以写多重载的方法来适应不同的参数。

如果实在觉得有很多不确定个数的参数可能会用时,那么可以用一个数组来存放这些参数(相同数据类型的参数)。
当然如果是不同类型的参数的话,你可以建立一个struct结构的结构数组在存放不同参数, 只是会影响性能。

 

以下转自MSDN

 

   用params修饰符声明的参数是参数数组。如果形参表包含一个参数数组,则该参数数组必须位于该列表的最后而且它必须是一维数组类型。例如,类型   string[]   和   string[][]   可用作参数数组的类型,但是类型   string[,]   不能。不可能将   params   修饰符与   ref   和   out   修饰符组合起来使用。   
    
  在一个方法调用中,允许以下列两种方式之一来为参数数组指定对应的参数:     
    
  赋予参数数组的参数可以是一个表达式,它的类型可以隐式转换(第   6.1   节)为该参数数组的类型。在此情况下,参数数组的作用与值参数完全一样。     
  或者,此调用可以为参数数组指定零个或多个参数,其中每个参数都是一个表达式,它的类型可隐式转换(第   6.1   节)为该参数数组的元素的类型。在此情况下,此调用创建一个长度对应于参数个数、类型与该参数数组的类型相同的一个数组实例,并用给定的参数值初始化该数组实例的元素,并将新创建的数组实例用作实参。     
  除了允许在调用中使用可变数量的参数,参数数组与同一类型的值参数(第   10.5.1.1   节)完全等效。   
    
  示例   
    
  using   System;   
  class   Test   
  {   
        static   void   F(params   int[]   args)   {   
              Console.Write("Array   contains   {0}   elements:",   args.Length);   
              foreach   (int   i   in   args)     
                    Console.Write("   {0}",   i);   
              Console.WriteLine();   
        }   
        static   void   Main()   {   
              int[]   arr   =   {1,   2,   3};   
              F(arr); 该数组实例作为值参数传递,等价于 F(new   int[]   {10,   20,   30,   40});
              F(10,   20,   30,   40);   
              F();     等价于F(new   int[]   {});
        }   
  }   
  产生输出   
    
  Array   contains   3   elements:   1   2   3   
  Array   contains   4   elements:   10   20   30   40   
  Array   contains   0   elements:   
  F   的第一次调用只是将数组   arr   作为值参数传递。F   的第二次调用自动创建一个具有给定元素值的四元素   int[]   并将该数组实例作为值参数传递。与此类似,F   的第三次调用创建一个零元素的   int[]   并将该实例作为值参数传递。第二次和第三次调用完全等效于编写下列代码:   
    
  F(new   int[]   {10,   20,   30,   40}); 
  F(new   int[]   {}); 
  
  执行重载决策时,具有参数数组的方法可能以它的正常形式或以它的扩展形式(第   7.4.2.1   节)成为适用的。只有在方法的正常形式不适用,并且在同一类型中尚未声明与方法的扩展形式具有相同签名的方法时,上述的方法扩展形式才可供选用。   
    
  示例   
    
  using   System;   
  class   Test   
  {   
        static   void   F(params   object[]   a)   {   
              Console.WriteLine("F(object[])");   
        }   
        static   void   F()   {   
              Console.WriteLine("F()");   
        }   
        static   void   F(object   a0,   object   a1)   {   
              Console.WriteLine("F(object,object)");   
        }   
        static   void   Main()   {   
              F();   
              F(1);   
              F(1,   2);   
              F(1,   2,   3);   
              F(1,   2,   3,   4);   
        }   
  }   
  产生输出   
    
  F();   
  F(object[]);   
  F(object,object);   
  F(object[]);   
  F(object[]);   

  *优先调用参数个数相对应方法。

  在该示例中,在同一个类中,已经声明了两个常规方法,它们的签名与具有参数数组的那个方法的扩展形式相同。因此,在执行重载决策时不考虑这些扩展形式,因而第一次和第三次方法调用将选择常规方法。当在某个类中声明了一个具有参数数组的方法时,同时再声明一些与该方法的扩展形式具有相同的签名的常规方法,这种情况比较常见。这样做可以避免为数组配置内存空间(若调用具有参数数组的方法的扩展形式,则无法避免)。   
    
  当参数数组的类型为   object[]   时,在方法的正常形式和单个   object   参数的扩展形式之间将产生潜在的多义性。产生此多义性的原因是   object[]   本身可隐式转换为   object。然而,此多义性并不会造成任何问题,这是因为可以在需要时通过插入一个强制转换来解决它。   
    
  示例   
    
  using   System;   
  class   Test   
  {   
        static   void   F(params   object[]   args)   {   
              foreach   (object   o   in   args)   {   
                    Console.Write(o.GetType().FullName);   
                    Console.Write("   ");   
              }   
              Console.WriteLine();   
        }   
        static   void   Main()   {   
              object[]   a   =   {1,   "Hello",   123.456};   
              object   o   =   a;   
              F(a);   
              F((object)a);   强制转换为object类型,而非object[]类型
              F(o);        o为object类型,而非object[]类型
              F((object[])o); 强制转换为object类型,而非object[]类型
        }   
  }   
  产生输出   
    
  System.Int32   System.String   System.Double   
  System.Object[]   
  System.Object[]   
  System.Int32   System.String   System.Double   
  在   F   的第一次和最后一次调用中,F   的正常形式是适用的,这是因为存在一个从自变量类型到参数类型的转换(这里,其实两者都是   object[]   类型)。因此,重载决策选择   F   的正常形式,而且将该参数作为常规的值参数传递。在第二次和第三次调用中,F   的正常形式不适用,这是因为不存在从自变量类型到参数类型的转换(类型   object   不能隐式转换为类型   object[])。但是,F   的扩展形式是适用的,因此重载决策选择它。因此,这两个调用都创建了一个具有单个元素的、类型为   object[]   的数组,并且用给定的参数值(它本身是对一个   object[]   的引用)初始化该数组的唯一元素。

 

C#中params的使用详解

转载自:http://blog.csdn.net/genispan/article/details/5466975

为了将方法声明为可以接受可变数量参数的方法,我们可以使用params关键字来声明数组,如下所示:

public static Int32Add(params Int32[] values)

{

     Int32 sum = 0;

     for (Int32 x = 0; x < values.Length; x++)

     {

     sum += values[x];

     }

     return sum;

}

     只有方法的最后一个参数才可以标记params,该参数必须标识一个一维数组,但类型不限。对方法的最后一个参数传递null或者0个数目的数组的引用都是合法的,如下面代码调用上面Add方法,编译正常,运行正常,和期望一样结果为0:

public static void Main()

{

     Console.WriteLine(Add());

}

     下面看一下如何编写一个可以接受任意数量、任意类型的参数的方法,也就是把上面方法的Int32改成Object[]就可以了:

public static void Main()

{

     DisplayTypes(new Object(), new Random(), "string", 10);

}

public static void DisplayTypes(params Object[] objects)

{

     foreach(Object o in objects)

     {

          Console.WriteLine(o.GetType());   

     }

}

输出:

System.Object

System.Random

System.String

System.Int32

 

注意,对于可接受可变数量参数的方法的调用会对性能造成一定的损失,因为数组是在堆上分配的,数组的元素还得初始化,数组的内存还得被垃圾回收器回收,为了减少这种没必要的性能损失,我们希望定义几个没有params关键字的重载方法,如System.String类的Concat方法,如下:

public static string Concat(object arg0);

public static string Concat(params object[] args);

public static string Concat(params string[] values);

public static string Concat(object arg0, object arg1);

public static string Concat(string str0, string str1);

public static string Concat(object arg0, object arg1, object arg2);

public static string Concat(string str0, string str1, string str2);

public static string Concat(object arg0, object arg1, object arg2, object arg3);

public static string Concat(string str0, string str1, string str2, string str3);

posted @ 2012-08-16 21:06  Danny Chen  阅读(1829)  评论(0编辑  收藏  举报