在reza发布的《是否可以从List中访问结构体的引用以进行更改?》帖子后,我脑海中浮现出一个问题。
因此,请考虑以下
据我所了解,在第一种情况下,
我还尝试进行反汇编,并发现:
1)对于
因此,请考虑以下
struct
和interface
(肯定不是很有用,但只是为了展示问题):public interface IChangeStruct
{
int Value { get; }
void Change(int value);
}
public struct MyStruct : IChangeStruct
{
int value;
public MyStruct(int _value)
{
value = _value;
}
public int Value
{
get
{
return value;
}
}
public void Change(int value)
{
this.value = value;
}
}
MyStruct
实现了 IChangeStruct
接口,因此我们可以直接在堆中更改其装箱副本,而无需进行拆箱并替换为新对象。以下代码演示了这一点:
MyStruct[] l1 = new MyStruct[]
{
new MyStruct(0)
};
Console.WriteLine(l1[0].Value); //0
l1[0].Change(10);
Console.WriteLine(l1[0].Value); //10
现在,让我们将数组改为 List<T>
,即:
List<MyStruct> l2 = new List<MyStruct>
{
new MyStruct(0)
};
Console.WriteLine(l2[0].Value); //0
l2[0].Change(10);
Console.WriteLine(l2[0].Value); //also 0
据我所了解,在第一种情况下,
l1 [0]
返回了对装箱结构的引用,而在第二种情况下,它是其他东西。我还尝试进行反汇编,并发现:
1)对于
MyStruct []
:
IL_0030: ldelema Utils.MyStruct
IL_0035: ldc.i4.s 10
IL_0037: call instance void Utils.MyStruct::Change(int32)
2) 对于 List<MyStruct>
:
IL_007c: callvirt instance !0 class [mscorlib]System.Collections.Generic.List`1<valuetype Utils.MyStruct>::get_Item(int32)
IL_0081: stloc.s CS$0$0001
IL_0083: ldloca.s CS$0$0001
IL_0085: ldc.i4.s 10
IL_0087: call instance void Utils.MyStruct::Change(int32)
但是我似乎不太能很好地解释它。
那么,List<T>
返回了什么呢?或者数组和 List<T>
是如何按索引返回元素的?或者这只适用于值类型,与引用类型无关?
P.S.:我确实明白一个值类型实例不能被改变,但是这个描述的问题让我明白了我从来没有意识到 List<T>
和数组的工作原理。
ldelema
只能在这些限制下工作) - Earlz