共计 1856 个字符,预计需要花费 5 分钟才能阅读完成。
语法糖背后的秘密
用 ILSpy 反编译下面代码时,会发现 params 关键字纯粹是编译器提供的语法糖:

public static void Demo(params int[] numbers) {/*...*/}
反编译后实际等价于:
public static void Demo(int[] numbers) {/*...*/}
关键结论 :编译器在调用处自动创建数组,Demo(1,2,3) 会被编译为Demo(new int[]{1,2,3})
性能对比实验
使用 BenchmarkDotNet 测试三种传参方式(测试代码包含内存分配统计):
[MemoryDiagnoser]
public class ParamsBenchmark
{[Benchmark]
public int ArrayParam() => SumArray(new[] {1, 2, 3, 4, 5});
[Benchmark]
public int ParamsParam() => SumParams(1, 2, 3, 4, 5);
[Benchmark]
public int GenericParam() => SumGeneric(1, 2, 3, 4, 5);
// 基准方法定义
int SumArray(int[] nums) => nums.Sum();
int SumParams(params int[] nums) => nums.Sum();
int SumGeneric<T>(params T[] nums) => nums.Sum(x => Convert.ToInt32(x));
}
测试结果显示:
– params 与直接数组传参性能相同
– 泛型方法会产生装箱开销,当 T 为 object 时分配内存增加 30%
典型应用场景
1. 日志系统
/// <summary>
/// 支持动态参数的日志方法
/// </summary>
public static void Log(string format, params object[] args)
{Console.WriteLine(string.Format(format, args));
}
// 使用示例:Log("用户 {0} 购买了 {1} 件商品", userId, count);
2. API 参数验证
/// <summary>
/// 检查任意参数是否为 null
/// </summary>
public static void ValidateNotNull(params object[] inputs)
{if (inputs.Any(x => x == null))
throw new ArgumentNullException();}
3. 数学计算
/// <summary>
/// 计算任意数量数值的平均值
/// </summary>
public static double Average(params double[] values)
{return values.Length == 0 ? 0 : values.Average();
}
装箱问题解决方案
当传递值类型时,params object[]会导致装箱:
// 产生装箱操作
PrintValues(params object[] values);
PrintValues(1, 2.0m, DateTime.Now);
// 解决方案:使用泛型约束
public static void PrintValues<T>(params T[] values) where T : struct
{// 避免装箱}
生产环境最佳实践
-
参数数量防御:
public static void SafeParams(params string[] items) {if (items.Length > 100) throw new ArgumentException("参数数量超过上限"); } -
高性能替代方案:
// 使用 Span 避免数组分配 public static void ProcessItems(Span<int> items) {/*...*/} -
AOT 编译注意:
- IL2CPP 等 AOT 方案可能不支持动态数组创建
- 需要预定义
[ParamsArray]特性
思考题延伸
如何设计支持 params 的扩展方法?考虑以下实现:
public static class CollectionExtensions
{public static void AddRange<T>(this ICollection<T> collection, params T[] items)
{foreach (var item in items)
collection.Add(item);
}
}
最终建议 :在性能敏感场景慎用 params,优先考虑显式数组或 Span
正文完
