为什么我不能将值类型的数组赋值给对象数组变量?

时间:2017-04-10 14:04:14

标签: .net vb.net roslyn

分配到a即可,分配到b会导致编译错误,为什么?

Dim a As Object() = { 1 }
Dim b As Object() = ({ 1 })

错误信息是:

  

BC30333'Integer()'类型的值无法转换为'Object()',因为'Integer'不是引用类型。

2 个答案:

答案 0 :(得分:2)

第一个示例有效,因为它推断并创建了一个Object数组。

然而,在第二个例子中,括号内的部分首先被评估,并被推断为Integer数组,然后它尝试将其分配给b(这当然不起作用) ,因为你不能像这样转换整个数组。)

根据MSDN文章Local Type Inference Option Infer将使编译器根据您为变量赋予的值来决定类型:

  

编译器根据初始化表达式的类型推断出变量的类型。

我想我已经弄清楚了:

因为必须正确完成所有操作,所以必须首先评估括号,然后语句的其余部分。编译器不知道您是否稍后尝试使用括号内的数组做更多的事情,直到它评估了整个语句。因此,它假定您需要一个整数数组。

在第一个示例中没有括号,因此可以直接评估整个语句,这将导致对象数组。当编译器发现它需要执行隐式转换时,它会选择Object(),因为那是你所说的你想要的,因为这是它唯一可以评估的东西。

答案 1 :(得分:0)

从字面上回答标题中的问题 - 因为值类型数组实际上只包含保存每个值类型的连续内存块,但对象数组由一个连续的内存块组成持有对象引用

当然,您可以通过装箱将值类型转换为对象引用。但是不能保证对象引用和值类型占用相同数量的内存,即使存在,单个连续内存块也不能同时保存值类型对象引用同时进行。

如果你确实需要执行这样的“赋值”,则必须以某种方式分配新的数组(例如,可能通过LINQ CastToArray方法),一旦创建,这两个数组就完全独立了 - 一个中值的更改不会被另一个中的盒装值的更改反映出来。