列表与数组中的索引器

Ash*_*ohn 10 c# value-type

如何在列表和数组中定义索引器.

List<MyStruct> lists=new List<MyStruct>();MyStruct结构在哪里.现在考虑一下 MyStruct[] arr=new MyStruct[10];

arr[0]给出了第一个Structure项的引用.但是lists[0]给了我一份它的副本.是否有任何理由这样做.此外,由于Int32结构是List<Int32> list1 =new List<Int32>();如何可以访问list1[0]或分配list1[0]=5在不可能的地方lists[0]._x=5

the*_*oop 10

尽管它们看起来相同,但数组索引器和列表索引器正在完全分开.

List<T>索引声明为带参数的属性:

public T this[int index] { get; set; }
Run Code Online (Sandbox Code Playgroud)

这会被编译为get_Itemset_Item访问参数时像任何其他方法一样被调用的方法.

数组索引器在CLR中有直接支持; 有一个特定的IL指令ldelema(加载元素地址),用于获取指向数组第n个元素的托管指针.然后,该指针可以被任何其他IL指令使用,这些指令将指针直接改变该地址处的东西.

例如,stfld(存储字段值)指令可以使用指定"this"实例的托管指针来存储字段,或者您可以使用指针直接在数组中的事物上调用方法.

在C#parlance中,数组索引器返回一个变量,但列表索引器返回一个.


Mar*_*ell 5

最后一点:

lists[0]._x=5
Run Code Online (Sandbox Code Playgroud)

实际上只是对你早期观点的重述:

arr[0]给出了第一个Structure项的引用.但是lists[0]给了我一份它的副本.

如果您编辑了它的副本,则更改将丢失到以太,即

var throwawayCopy = lists[0];
throwawayCopy._x = 5;
// (and never refer to throwawayCopy again, ever)
Run Code Online (Sandbox Code Playgroud)

因为这几乎肯定不是你想要的,编译器不会让你.然而,可变的结构是邪恶的.这里更好的选择是不要使用可变结构.他们咬了一口.


把它降低到一个水平,到一个简单而具体的例子:

using System;
struct Evil
{
    public int Yeuch;
}
public class Program
{
    public static void Main()
    {
        var pain = new Evil[] { new Evil { Yeuch = 2 } };
        pain[0].Yeuch = 27;
        Console.WriteLine(pain[0].Yeuch);
    }
}
Run Code Online (Sandbox Code Playgroud)

这将编译(在这里查看最后两行):

L_0026: ldloc.0 <== pain
L_0027: ldc.i4.0 <== 0
L_0028: ldelema Evil <== get the MANAGED POINTER to the 0th element
                           (not the 0th element as a value)
L_002d: ldc.i4.s 0x1b <== 27
L_002f: stfld int32 Evil::Yeuch <== store field

L_0034: ldloc.0 <== pain
L_0035: ldc.i4.0 <== 0
L_0036: ldelema Evil <== get the MANAGED POINTER to the 0th element
                           (not the 0th element as a value)
L_003b: ldfld int32 Evil::Yeuch <== read field
L_0040: call void [mscorlib]System.Console::WriteLine(int32) <== writeline
L_0045: ret 
Run Code Online (Sandbox Code Playgroud)

它从来没有真正与结构作为一个值进行对话- 没有副本等

  • 正是@sehe;对于数组,“._x=5”对*结构引用*进行操作,从而更新数组**内的项。但是将它分配给变量会破坏它,因为它取消引用/复制。 (2认同)