C# - 编译器错误 - 将int []赋给object []

时间:2011-09-04 17:01:56

标签: c# compiler-errors

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            object[] obj = new object[3];
            obj[0] = new object();
            obj[1] = "some string";
            obj[2] = 10;

            string[] strings = new string[] { "one", "two", "three" };
            obj = strings; //---> No Error here, Why ?

            int[] ints = new int[] { 1, 2, 3 };
            obj = ints; /*-> Compiler error - Cannot implicitly convert type 'int[]' to 'object[]', Why ?*/ 
        }
    }
}

执行上述步骤时出现编译器错误。但是,在上一步中,没有错误。有人能解释一下这种行为吗?我正在使用VS 2010。

  

编辑 - 为了完整起见,再次,这将无法编译 - .NET 4.0中的差异支持现已被清除。可以使用新的关键字 in out 使用泛型类型参数。

    List<object> objectList = new List<object>();
    List<string> stringList = new List<string>();
    objectList = stringList;

5 个答案:

答案 0 :(得分:6)

只有引用类型数组(如String)可以分配给其他引用类型的数组(如Object)。由于int是值类型,因此可能无法将其数组分配给其他类型的数组。

更具体地说,这称为array covariance。它仅在存储在阵列中的位模式与目标类型兼容时才有效。例如,String[]中的位都是对字符串的引用,可以安全地复制到存储对象引用的内存位置。但是,值类型数组存储元素的实际数据(而不是仅仅引用它们)。这意味着int[]将实际的32位整数存储在数组的元素中。由于无法将32位整数安全地复制到存储对象或任何其他类型的引用的内存位置,因此无法将它们的数组分配给任何其他类型的数组。

请注意,从技术上讲,int的位可以安全地复制到存储uint的内存位置(反之亦然)。这意味着您应该能够执行int[] x = new uint[10]之类的操作。这实际上不是协方差,C#不允许它。但是,它在CLR中是合法的,你可以说服C#让你这样做。

答案 1 :(得分:2)

stringobject都是引用类型。也就是说,这些类型的变量实际上存储了指向内存中其他位置的指针。 int是值类型。也就是说,数据直接存储在声明变量的位置。

这意味着引用类型数组与值类型数组根本不同。引用类型数组存储为指针数组。因为指针的大小都相同,这意味着将string[]重新解释为object[] simpy意味着在访问数组中的项时调整类型检查(粗略地说)。

但是,在int[]中,值直接存储在数组中; int值连接在一起。没有指针。这意味着要将int[]重新解释为object[],需要将存储在数组中的每个值装入对象中。因此,为什么你不能使用简单的强制转换或赋值来实现它 - 这是一个创建新数组的O(n)操作。相反,您可以使用Array.Copy来处理所有拳击。

答案 2 :(得分:1)

我看到的是一个引用类型数组可以分配另一个引用类型数组,而值类型数组则不能。对我有意义

答案 3 :(得分:1)

为什么这不起作用在这里的许多答案中说明,所以我不会尝试复制粘贴他们说的话。

如果您或其他人真的想这样做(将int[]转换为object[])由于某种原因,您可以像这样使用LINQ:

int[] ints = new int[] { 1, 2, 3 };
object[] obj_ints = (from i in ints select i).Cast<object>().ToArray();

答案 4 :(得分:0)

如果您安装了Visual Studio,您将在VC#下的某处找到C#语言描述作为doc文件。第12.5章涉及协方差,并在那里说

  

对于任何两个引用类型A和B,如果是隐式引用   存在转换(第6.1.6节)或显式引用转换(第6.2.4节)   从A到B,然后也存在相同的参考转换   数组类型A [R]到数组类型B [R],其中R是任何给定的   rank-specifier(但两种数组类型都相同)。这种关系   被称为阵列协方差。

这可能无法解答您的问题,但在规范中这是故意做出的决定。