CA1819: le proprietà non devono restituire matrici. Questo succede solo con gli array? Se sì, perché?

3

Ho una domanda su CA1819 msdn warning warning.

La regola è: le matrici restituite dalle proprietà non sono protette da scrittura, anche se la proprietà è di sola lettura. Per mantenere l'array a prova di manomissione, la proprietà deve restituire una copia dell'array. In genere, gli utenti non comprenderanno le implicazioni di prestazioni avverse della chiamata di tale proprietà. In particolare, potrebbero utilizzare la proprietà come proprietà indicizzata.

Comprendo la regola.

Voglio sapere se questo succede solo con gli array? Se sì, perché?

    
posta Kriss 09.09.2013 - 17:00
fonte

2 risposte

6

Gli array sono tipi di riferimento. Quello è quando una proprietà restituisce un oggetto di matrice che sta restituendo un puntatore / riferimento alla sua matrice interna. Il chiamante della proprietà ora può modificare quella matrice interna (dato che hanno un puntatore), questo è generalmente indesiderato. Per fermarlo, puoi restituire una copia dell'array interno, ma ora esegui un'allocazione di memoria e copia ogni volta che la proprietà viene utilizzata, e dato che le proprietà sono pensate per essere leggere e non va bene.

Questo succede con qualsiasi tipo di riferimento che è mutabile. Se si dispone di un riferimento privato a un tipo di riferimento mutabile (Come un flusso, elenco o dizionario) e si restituisce tale riferimento in una proprietà di quanto il chiamante può modificare i dati. Se si dispone di un tipo di valore (structs in C #) di quello che viene sempre copiato quando viene restituito dalla proprietà, in modo che il chiamante non possa modificare la versione interna dei dati.

    
risposta data 09.09.2013 - 17:07
fonte
3

Bene, per prima cosa .net ha introdotto IReadOnlyList e IReadOnlyDictionary che risolvono questo problema per i generici (che è preferibile ad un array di base), in precedenza avresti dovuto creare la tua interfaccia per vedere la stessa performance con stessa restrizione.

Il problema di base, e no, non è limitato agli array, è che si desidera fornire un metodo per accedere a un gruppo di elementi senza richiedere che vengano iterati, ma non si vuole che il consumatore della propria API sia aggiunta o eliminazione di elementi, ma in precedenza tutte le interfacce incorporate che consentono ciò che si desidera, consentivano anche ciò che non si desidera.

La soluzione suggerita è al contempo inefficiente (la creazione di un clone è lenta) e fuorviante - il consumatore ottiene una matrice che pensa che può modificare e avere quell'effetto l'oggetto che la ha restituita. Cioè pensa che se aggiunge un elemento e poi chiama di nuovo la proprietà, otterrà un array con p + 1 elementi. Si aspetta anche che o.ItemArray.Equals (o.ItemArray). Nessuna di queste aspettative sarà vera.

Come problema pratico, questo non è più un problema se puoi usare la versione corretta del framework e qualcosa di diverso da un array.

Per quanto riguarda il problema di prestazioni ...

if(o.ItemArray.Equals(o.ItemArray) || o.ItemArray.Equals(o2.ItemArray))

Crea 4 copie di un array potenzialmente grande.

Modifica in risposta al commento:

Questo non è un problema specifico degli array. Elenco e dizionari sono anche modificabili.

IList<string> lst = new List<string>();
lst.Add("hello");
lst[0]="bye";
Console.WriteLine(lst[0]);

E l'esempio di codice sopra mostra i problemi con l'elenco mutabile come proprietà. Supponiamo che io abbia avuto una lezione, Saluti, che contiene un elenco di parole e frasi che useresti quando incontri qualcuno. Ciao, Ciao, Hola, Ehi amico, Whats up! Como esta e così via. Quindi, ho una proprietà Words e restituisco il precedente lst. Puoi quindi eseguire immediatamente la terza riga e cambiare il mio "ciao" in "ciao" - per tutti quelli che hanno un riferimento a quell'istanza della classe.

Ma come ho detto, nel 4.5, avresti aggirato questo facendo sì che la tua lista fosse IReadOnlyLst e, usando questo ...

return (IReadOnlyList<string>) lst;
    
risposta data 09.09.2013 - 17:48
fonte

Leggi altre domande sui tag