什么是数组索引?

4

我知道,例如List<T>索引器类似于属性。这是从msdn上摘取的:

索引器允许类或结构的实例被索引,就像数组一样。索引器类似于属性,除了它们的访问器需要参数。

但我不明白为什么会发生以下情况:

int[] myArray = new int[0];
List<int> myList = new List<int>();

Interlocked.Increment(ref myArray[0]);  // fine

Interlocked.Increment(ref myList[0]);   //CS0206    A property or indexer may not be passed as an out or ref parameter

他们不应该以相同的方式工作吗?

1
请查看Mike Chamberlain在重复问题上的回答。尽管它没有被标记为正确答案,但它是更详细的,并且非常清楚地解释了为什么这是不可能的。希望能有所帮助。 - Christos
2
@Christos 我认为这并没有回答问题。 - MistyK
@Christos 我不是在问错误。 - Arthur Castro
@Christos 我同意 Zbigniew 的观点。真正的问题是为什么它适用于数组,而不是为什么它不适用于列表索引器。 - juharr
@ArthurCastro 好的,我重新打开了这个问题。希望你能找到你想要的答案。 - Christos
1
这是因为数组是特殊的。 - Dennis_E
2个回答

7

List<T> 的索引器允许您使用属性(方法)访问元素,使其看起来像一个数组。您无法像编写以下内容那样通过 ref 传递生成的方法:

Interlocked.Increment(ref myList.GetItem.get_Item(0));

但是,通过索引器无法访问数组元素。访问数组元素在CLR中直接支持。因此,`array[i]` 返回一个可作为 `ref` 传递的变量。
从C#规范中可以看到:
尽管访问索引器元素的语法与访问数组元素的语法相同,但是索引器元素不被归类为变量。因此,不能将索引器元素作为ref或out参数传递。
这是 `List` 的索引器(内部使用数组):
public T this[int index]
{
    get
    { // some checks removed 
        return _items[index];
    }

    set { _items[index] = value;}
}

来自IL方面:

访问数组元素会生成这个直接的IL指令:

IL_0014: ldelem.i4

通过索引器访问列表元素会生成这个指令:

IL_001b:  callvirt   instance !0 class [mscorlib]System.Collections.Generic.List`1<int32>::get_Item(int32)

所以,它是相同的C#语法。但生成的IL完全不同。


尽管访问索引器元素的语法与访问数组元素的语法相同,但索引器元素不被归类为变量。我想要阅读的内容正是:从数组中返回的索引返回变量本身。 - Arthur Castro

4

这是因为索引器是属性,并且属性最终是函数。因为它们是函数,所以它们不像数组索引那样(必须)指向内存中的特定位置。如果语言允许这样做,开发人员将能够轻松地打破引用和语义,导致程序无法正常工作。以下是一个例子:

public class Foo {
        public int this[int x] {
            get {
                return 1;
            }
            set {
                //meh. whatever. 
            }
        }
    }

如果我将 Foo[0] 作为 out 参数传递,发生了什么?在这种情况下,我甚至不设置任何内容。这完全破坏了 refout 的语义。

尽管我会在这里引用第174行,但你比我快了……http://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs - Matthew Layton
索引器是属性,属性最终是函数。使用相同的逻辑,数组索引也是属性,最终也是函数,但它们的行为不同,正如您在问题中所看到的示例。 - Arthur Castro
不,索引和索引器是两个不同的东西。 - aquinas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接