C# 协方差行为中的数组对象[]

C# 协方差行为中的数组对象[],c#,covariance,C#,Covariance,(问题不是我的) 公认的答案表明这是因为数组协方差(为了更好地理解,请阅读问题和答案) 现在我的情况是,虽然我无法将int[]赋值给object[],因为int是值类型(struct),但我想知道为什么我现在可以这样做: var arrayOfObjects = new object[] { 58, 58, 78 };// it accepts values types as initializers! 如果我正在初始化数组对象的值类型,为什么会这样?不应该是互易的,也不接受值类型?因为您(隐

(问题不是我的)

公认的答案表明这是因为数组协方差(为了更好地理解,请阅读问题和答案)

现在我的情况是,虽然我无法将
int[]
赋值给
object[]
,因为
int
是值类型(
struct
),但我想知道为什么我现在可以这样做:

var arrayOfObjects = new object[] { 58, 58, 78 };// it accepts values types as initializers!
如果我正在初始化数组对象的值类型,为什么会这样?不应该是互易的,也不接受值类型?

因为您(隐式地)将一个项目一个接一个地强制转换到
对象中。您没有将
int[]
数组分配给
object[]
变量-您正在从单个
int
值(隐式转换和装箱)创建
object[]
变量

要在不使用数组初始值设定项的情况下显示此项,请执行以下操作:

object[] objarr = new object[1];
objarr[0] = 42; // Fine, translates basically into objarr[0] = (object)42;

int[] intarr = new int[1];
intarr[0] = 42; // Also fine

objarr = intarr; // No can do!

这里您不是在构建一个
int[]
,而是在构建一个
对象[]
。你也可以把其他东西装箱:

var arrayOfObjects = new object[] { true, "false", 1, 10, new StringBuilder() }

要从编译器的角度完成此观点,请给出以下语句:

void Main()
{
    object[] or = new object[] { 1, 2 };
}
这是编译器发出的IL:

IL_0001:  ldc.i4.2    
IL_0002:  newarr      System.Object
IL_0007:  stloc.1     // System.Object[]
IL_0008:  ldloc.1     // System.Object[]
IL_0009:  ldc.i4.0    
IL_000A:  ldc.i4.1    
IL_000B:  box         System.Int32
IL_0010:  stelem.ref  
IL_0011:  ldloc.1     // System.Object[]
IL_0012:  ldc.i4.1    
IL_0013:  ldc.i4.2    
IL_0014:  box         System.Int32
IL_0019:  stelem.ref  
IL_001A:  ldloc.1     // System.Object[]
IL_001B:  stloc.0     // or
IL_001C:  ret      

编译器获取这些值,对值类型(
int
)执行
操作,然后调用
stelem.ref
,它将一维数组中提供索引处的元素值替换为推送到堆栈上的ref(type O)值。

这被调用。
int
值正在从值类型转换为对象。数组与协方差无关。我看不出您在代码中使用协方差的位置。因此,如果我使用十进制值(5.2)初始化数组,整个值是否会保留在装箱中?或者它会改变(比如说5)?@先生,它会被保存下来。
decimal
将被装箱,不会有任何隐式转换。