List <T>和数组索引器之间有什么区别?

hor*_*rgh 6 c# arrays generics struct

在我的脑海中提出的问题是否可以从List中访问结构的引用以进行更改?reza线程.

所以,请考虑以下structinterface(definetely不是非常有用,但只是为了显示这个问题):

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

现在,让我们将数组更改为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
Run Code Online (Sandbox Code Playgroud)

据我所知,在第一种情况下,将参考文献l1[0]返回到盒装结构中,而在第二种情况下 - 它是另一种结果.

我也试图反汇编这个并发现:

1)用于MyStruct[]:

IL_0030:  ldelema    Utils.MyStruct
IL_0035:  ldc.i4.s   10
IL_0037:  call       instance void Utils.MyStruct::Change(int32)
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)

但我似乎还没有准备好解释它.

那么,List<T>回报是什么?或者如何List<T>通过索引进行数组和返回元素?或者这只是值类型的情况,与引用类型无关?

PS:我确实理解一个人不能改变一个值类型实例,但所描述的问题让我理解,我从未意识到如何List<T>和数组工作.

SLa*_*aks 9

.Net可以使用ldelema指令(数组元素的加载地址)就地寻址数组元素.

这允许您直接在数组元素上操作而无需复制它们.(这也是为什么你可以传递一个数组元素作为refout参数)

List<T>没有这种能力.相反,list[i]它只是语法糖list.get_Item(i),这是一个返回结构副本的普通方法调用.