considerare i seguenti due tipi di dati:quale sia la differenza tra il campo indicizzatore e qualsiasi altro indicizzatore oggetto
class C
{
public int I { get; set; }
}
struct S
{
public int I { get; set; }
}
Cerchiamo di usarli all'interno della lista, ad esempio:
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++; // (a) CS1612 compilation error
Come previsto, ci errore di compilazione sulla riga (a)
: CS1612 Cannot modify the return value of 'List<UserQuery.S>.this[int]' because it is not a variable
. Questo va bene, perché in realtà stiamo cercando di modificare la copia temporanea di S
, che è valore-r nel dare contesto.
Ma cerchiamo di fare stessa cosa per un 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++; // (b)
E .. questo funziona.
Ma
var s_arr_list = (IList<S>) s_arr;
s_arr_list[0].I++;
non si compila, come previsto.
Se guardiamo il prodotto IL, troveremo seguente:
IL_0057: ldloc.1 // s_arr
IL_0058: ldc.i4.0 // index
IL_0059: ldelema UserQuery.S // manager pointer of element
ldelema
carichi indirizzo del elemento della matrice in cima alla pila di valutazione. Tale comportamento è previsto con l'array fixed
e i puntatori non sicuri. Ma per un contesto sicuro questo è un po 'inaspettato. Perché c'è un caso speciale non ovvio per gli array? Qualunque motivo per cui non vi è alcuna opzione per ottenere lo stesso comportamento per i membri di altri tipi?
Perché trovi 'ldelema' inaspettato per un contesto sicuro? Carica un riferimento gestito (quindi controllato dal GC), come 'ldloca' o' ldflda'. Quando usi 'ref' in C#, è esattamente questo. – IllidanS4