不错的发现!
这是未定义的行为吗?
不,这是设计使然。奇怪的设计,但却是有意为之。
这取决于.Net框架版本/Mono版本吗?
不会。所有版本的 C# 都有此行为。
这是 C# 的一些有趣规则发生冲突的结果。
第一个相关规则是:具有 params 数组的方法可以以“正常”或“扩展”形式调用。正常形式就好像没有“params”。扩展形式采用参数并将它们捆绑到自动生成的数组中。如果两种形式都适用,那么普通形式胜过扩展形式.
现在看来,这或许是明智的。如果您手头有一个对象数组,那么您很可能希望传递对象数组,而不是包含对象数组的数组。
第二条相关规则是 C# 允许当元素类型是引用类型时不安全的数组协方差。也就是说,字符串数组可以隐式转换为对象数组。您会注意到这有两个含义。首先,这意味着当你有一个对象数组时,它可能actually是一个字符串数组,因此将海龟放入该对象数组中可能会导致类型错误。这是非常令人惊讶的!您期望每个对象数组都可以接受任何对象,但在 C# 中并非如此。一些物体阵列正在撒谎。
第二个含义是:由于将海龟放入真正的字符串数组中必须抛出,这意味着每次将某些内容放入基本类型数组时,运行时必须验证类型是否检查。所以数组写入在 C# 中是非常昂贵的every写,这样极少数的坏写就可以被捕获。
这是一团糟,这就是为什么不安全的数组协方差在我的不幸的 C# 功能列表中名列前茅。
这两条规则的结合解释了你的观察结果。字符串数组可转换为对象数组,因此该方法适用于正常形式。
对于整数数组,协方差不适用于值类型。因此,整数数组不可转换为对象数组,因此该方法不适用于其正常形式。但整数数组是一个对象,因此它适用于扩展形式。
也可以看看:
为什么 params 会有这样的行为? https://stackoverflow.com/questions/2210519/why-does-params-behave-like-this/2210603#2210603
您的问题可以说是重复的:
有没有办法区分 myFunc(1, 2, 3) 和 myFunc(new int[] { 1, 2, 3 })? https://stackoverflow.com/questions/9685259/is-there-a-way-to-distingish-myfunc1-2-3-from-myfuncnew-int-1-2-3/9711427#9711427