【问题标题】:Why cant I assign array of value type into object array variable?为什么我不能将值类型的数组分配给对象数组变量?
【发布时间】:2017-04-10 14:04:13
【问题描述】:

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

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

错误信息是:

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

【问题讨论】:

  • 因为Integer is not a reference type。用String试试没有问题。
  • 它将类型推断为Integer
  • @MichalHosala,我的错误,对此感到抱歉。
  • 如果你将整数放入其中,为什么要将数组声明为Object()
  • 投反对票的人会介意说出他/她不喜欢这个问题的什么地方吗?它格式正确,清楚地描述了我的要求。

标签: .net vb.net roslyn


【解决方案1】:

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

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


根据MSDN文章Local Type InferenceOption Infer会让编译器根据你给变量的值来决定类型:

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

我想我已经明白了:

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

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

【讨论】:

  • 所以你基本上是在说没有用括号括起来的隐式类型数组永远不会有自己的类型,它总是依赖于上下文?如果这是真的,那么我认为这意味着我开始的这个roslyn bug report 是无效的,你同意吗?
  • @MichalHosala :我不喜欢 Roslyn,但一般编译器倾向于先计算括号(毕竟,正确的数学应该是这样计算的)。
  • 你是对的,当然,我只是认为{ 1 } 有自己的类型,不管括号。
  • @MichalHosala :我不认为它有自己的类型,没有。编译器在编译时/运行时确定(推断)类型。在这种情况下是Object()Integer()
  • 嗯,好吧,我认为 C# 代码 new[] { 1 } 的 VB.NET 类比是 { 1 },但显然不是这样,因为 new[] { 1 } 有自己的类型。似乎({ 1 }) 的行为方式更相似。
【解决方案2】:

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

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

如果您确实需要执行这样的“分配”,则必须以某种方式分配一个新数组(例如,可能通过 LINQs CastToArray 方法),一旦创建,然后两个数组完全独立 - 一个数组中的值的更改不会反映在另一个数组中的装箱值的更改中。

【讨论】:

  • 是的,您正在回答标题中的问题,但不是关于问题描述的其余部分。
猜你喜欢
  • 2014-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-05
  • 2021-12-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多