Consider the following two types of data:
class C { public int I { get; set; } } struct S { public int I { get; set; } }
Try using them inside a list, for example:
var c_list = new List<C> { new C { I = 1 } }; c_list[0].I++; var s_list = new List<S> { new S { I = 1 } }; s_list[0].I++;
As expected, there is a compilation error on line (a) : CS1612 Cannot modify the return value of 'List<UserQuery.S>.this[int]' because it is not a variable . This is great because we are actually trying to change the temporary copy of S , which is the r-value when providing the context.
But try to do the same for the array:
var c_arr = new[] { new C { I = 1 } }; c_arr[0].I++; var s_arr = new[] { new S { I = 1 } }; s_arr[0].I++;
And .. it works.
But
var s_arr_list = (IList<S>) s_arr; s_arr_list[0].I++;
will not compile as expected.
If we look at the resulting IL, we find the following:
IL_0057: ldloc.1 // s_arr IL_0058: ldc.i4.0 // index IL_0059: ldelema UserQuery.S // manager pointer of element
ldelema loads the address of an array element at the top of the evaluation stack. This behavior is expected with an array of fixed and unsafe pointers. But for a safe context, this is a bit unexpected. Why is there a special non-obvious case for arrays? Anyone why there is no way to achieve the same behavior for members of other types?
arrays c # data-structures
lorond
source share