C#中null条件与合并运算符在params方法调用中的计数差异疑问
C#中params参数空值处理的疑问
以下是测试代码:
static void Main(string[] args) { F1(null); } public static void F1(int[] values) { F2(1, values?[0] as object ?? new object[0]); F2(2, values?.Select(v => (object)v) ?? new object[0]); F2(3, values?.Select(v => (object)v).ToArray() ?? new object[0]); } public static void F2(int idx, params object[] values) { Console.WriteLine($"count {idx}: '{values?.Count()}'"); }
代码运行输出:
count 1: '1' count 2: '1' count 3: '0'
在Visual Studio即时窗口中,以下表达式结果均为null:
values?[0] null values?.Select(v => (object)v) null values?.Select(v => (object)v).ToArray() null
为何前两个输出的计数为1?
原因解析
问题核心在于params参数的匹配规则,以及??运算符的类型推断:
params数组的匹配逻辑
- 若传入参数的类型与
params定义的数组类型完全一致,直接将该数组作为params参数使用。 - 若传入参数是单个非数组类型的
object,C#会自动把它包装成一个长度为1的object[]数组。
- 若传入参数的类型与
逐个分析调用逻辑
- 调用1:
values?[0] as object的类型是object,new object[0]是object[]。??运算符会将右侧的object[]隐式转换为object类型,最终传入F2的是一个值为new object[0]的object。params将这个object包装成长度为1的数组,因此计数为1。 - 调用2:
values?.Select(...)返回IEnumerable<object>,它和new object[0]的公共基类是object,所以??的结果类型是object。传入的object(空数组)被包装成长度为1的数组,计数为1。 - 调用3:
values?.Select(...).ToArray()返回object[],和new object[0]类型完全一致,??的结果类型是object[]。此时传入参数类型与params的object[]匹配,直接使用这个空数组,因此计数为0。
- 调用1:
内容的提问来源于stack exchange,提问作者Gigi
相关产品推荐
相关产品推荐

