What is the difference between List<T> and array indexers?
arrays, c#, generics, struct
Solution
.Net can address array elements in-place, using the `ldelema` instruction (load address of array element).
This allows you to operate directly on array elements without copying them. (this is also why you can pass an array element as a `ref` or `out` parameter)
`List<T>` has no such capability. Instead, `list[i]` is just syntactic sugar for `list.get_Item(i)`, which is a normal method call that returns a copy of the struct.
Problem
The question raised in my mind after Is it possible to access a reference of a struct from a List to make changes? thread by reza. So, consider the following `struct` and `interface` (definetely not very useful, but just to show the issue): ``` 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` implements `IChangeStruct`, so we can change a boxed copy of it right in the heap without unboxing and replacing with a new one. This can be demostrated with the following code: ``` MyStruct[] l1 = new MyStruct[] { new MyStruct(0) }; Console.WriteLine(l1[0].Value); //0 l1[0].Change(10); Console.WriteLine(l1[0].Value); //10 ``` Now, let's change array to `List<T>`, i.e.: ``` 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 ``` As far as I understood, in the first case `l1[0]` returned the referense to the boxed struct, while in the second - it was smth else. I also tried to disassemble this and found: 1) For `MyStruct[]`: ``` IL_0030: ldelema Utils.MyStruct IL_0035: ldc.i4.s 10 IL_0037: call instance void Utils.MyStruct::Change(int32) ``` 2) For `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) ``` But I appeared to be not ready to interpret it well. So, what did the `List<T>` return? Or how do array and `List<T>` return elements by index? Or is this only the case with value types and has nothing to do with reference types? P.S.: I do understand that one must not change a value type instance, but the described issue made me understand, I never realized how `List<T>` and array work.