c# -编译错误-将int[]赋值给对象[]时

本文关键字:赋值 对象 int 编译 错误 | 更新日期: 2023-09-27 18:07:36

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中的方差支持现在已经清理了。可以使用新的关键字inout与泛型类型参数。

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

c# -编译错误-将int[]赋值给对象[]时

只有引用类型的数组(如String)可以赋值给其他引用类型的数组(如Object)。由于int是值类型,它的数组不能赋值给其他类型的数组

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

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

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

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

然而,在int[]中,值直接存储在数组中;整型值被连接在一起。不涉及指针。这意味着要将int[]重新解释为object[]需要将存储在数组中的每个值装入一个对象。这就是为什么不能使用简单的强制类型转换或赋值—这是一个创建新数组的O(n)操作。相反,您可以使用Array.Copy,它为您处理所有的装箱。

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

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

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

我看到的是引用类型的数组可以被赋值给另一个引用类型的数组,而值类型的数组却不能。Make sense to me

如果你安装了Visual Studio,你会发现c#语言规范作为文档文件在vc#下的某个地方。第12.5章讨论协方差,这里写着

对于任意两个引用类型A和B,如果是隐式引用存在转换(§6.1.6)或显式引用转换(§6.2.4)从A到B,那么同样的引用转换也存在数组类型A[R]到数组类型B[R],其中R是任意给定的等级说明符(但两种数组类型相同)。这种关系称为数组协方差

这可能不能回答你的问题,但这是规范中深思熟虑的决定。