问题描述
考虑到这一点code
Considering this code
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string[] strings = new string[] { "Test1", "Test2", "Test3" };
int[] ints = new int[] { 1, 2, 3, 4 };
Test(strings);
Test(ints);
}
public static void Test(params object[] objects)
{
}
}
}
和本页面https://msdn.microsoft.com/fr-ca/library/w5zay9db.aspx
我希望(params对象[]对象)是一个元素的数组一个字符串[]作为第一个元素,但是当我调试,我看到(params对象[]对象)是{测试1 的Test2,Test3的}。
I would expect (params object[] objects) to be an array of one element with a string[] as the first element, but when I debug, I see that (params object[] objects) is { "Test1", "Test2", "Test3" }.
然而,一个int [],我得到一个Object []使用int []作为第一要素。
However, with an int[], I get an object[] with int[] as first element.
这是不确定的行为?这是否依赖于.NET Framework版本/单声道版本?
Is this undefined behavior? Does that depend on the .Net framework version / Mono version?
推荐答案
- 尼斯找到!
这是不确定的行为?
没有。这是设计的行为。怪异的设计,但设计。
No. This is by-design behaviour. Weird design, but by design.
不依赖于.NET Framework版本/单声道版本?
没有。 C#的所有版本都有这种行为。
No. All versions of C# have this behaviour.
这是C#的一些有趣的规则碰撞的结果。
This is a consequence of the collision of some interesting rules of C#.
第一个相关的规则是:用参数数组的方法可以在常规或膨胀的形式被调用。范式是因为如果没有PARAMS。扩展的形式取PARAMS并将它们捆绑成一个自动生成的数组。 如果两种形式都适用,则正常形态战胜扩展形式
The first relevant rule is: a method with a params array may be called in either "normal" or "expanded" form. Normal form is as if there was no "params". Expanded form takes the params and bundles them up into an array that is automatically generated. If both forms are applicable then normal form wins over expanded form.
现在,也许似乎是合理的;如果你手中有对象的数组,赔率是好的,你想传递对象数组,而不是包含对象的数组的数组。
Now, that perhaps seems sensible; if you have an array of objects in hand, odds are good that you want to pass the array of objects, not an array that contains an array of objects.
第二个相关的规则是,C#允许当某个元素是引用类型 不安全阵列协方差。也就是说,一个字符串数组,可以隐式转换为对象的数组。你会注意到,这有两层含义。首先,这意味着,当你有对象的数组,它可能的真正的是一个字符串数组,所以把,说,龟成对象的数组可能会导致错误类型。这是非常令人惊讶!你期望的对象每个数组可以采取任何对象,但不是在C#如此。对象的一些阵列在撒谎。
The second relevant rule is that C# allows unsafe array covariance when the element type is a reference type. That is, an array of strings may be converted to an array of objects implicitly. You'll note that this has two implications. First, it means that when you have an array of objects, it might actually be an array of strings, so putting, say, a turtle into that array of objects might cause a type error. This is very surprising! You expect that every array of objects can take any object, but that is not true in C#. Some arrays of objects are lying.
第二个含义是:既然把那乌龟到什么是真正的字符串必须抛出的数组,这意味着每次你把东西到基本类型的数组时,运行时必须验证类型检查。所以数组写入是昂贵的额外在C#中的每个的写,这样写不好的微乎其微少数人可以被捕获。
The second implication is: since putting that turtle into what is really an array of strings must throw, it means that every time you put something into an array of base type, the runtime must verify that the types check. So array writes are extra expensive in C# on every write, so that the vanishingly small minority of bad writes can be caught.
这是一个烂摊子,这就是为什么不安全的阵列协方差均居我不幸的C#功能列表。
This is a mess, and this is why unsafe array covariance tops my list of unfortunate C# features.
这两个规则的组合说明你的意见。字符串数组可转化为对象的数组,并且因此该方法适用于正常形式
The combination of these two rules explains your observations. The array of strings is convertible to an array of objects, and therefore the method is applicable in normal form.
有关整数数组,那么,协方差并不适用于价值类型。所以整数数组是无法转换为对象的数组,所以这种方法并不适用于正常状态。但是int数组是一个对象,因此它适用于展开形式。
For the array of ints, well, covariance does not apply to value types. So the array of ints is not convertible to an array of objects, so the method is not applicable in its normal form. But an array of ints is an object, so it is applicable in expanded form.
另请参阅:
Why不PARAMS这样的表现?
您的问题可以说是重复的:
Your question is arguably a duplicate of:
Is有办法distingish myFunc的(1,2,3)从myFunc的(新INT [] {1,2,3})?
这篇关于C#params对象[]奇怪的行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!