C#如何实现不定参数个数的函数

BQ 2004-05-05 08:43:41
就象C中的printf,可以不定参数的个数
...全文
1574 2 点赞 打赏 收藏 举报
写回复
2 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
BQ 2004-05-05
俺知道怎么做了,查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(10, 20, 30, 40);
F();
}
}
产生输出

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);
F(o);
F((object[])o);
}
}
产生输出

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[] 的引用)初始化该数组的唯一元素。


还是谢谢
  • 打赏
  • 举报
回复
greatsft 2004-05-05
一般的方法可以自己写多重载的方法来适应不同的参数(一般也是这样做的);
如果你实在觉得有很多不确定个数的参数可能会用时
那么你可以用一个数组来存放这些参数(相同数据类型的参数);
当然如果是不同类型的参数的话,你可以建立一个struct结构的结构数组在存放不同参数,
当然效率上肯定很有问题.

不过我觉得一般方法有很多参数的话肯定是选择重载的!

还有其实c中的printf也并是说他可以有多个参数,他只是有个专门的
存放参数的缓冲区类似我上面说的数组的概念

总结:建议还是选择方法重载吧

wish u good luck
Greatsft
  • 打赏
  • 举报
回复
相关推荐
发帖
C#
加入

10.6w+

社区成员

.NET技术 C#
申请成为版主
帖子事件
创建了帖子
2004-05-05 08:43
社区公告

让您成为最强悍的C#开发者