Domanda

Secondo [MSDN: Linee guida per l'uso dell'array] ( http://msdn.microsoft.com/en-us/library/k2604h5s (VS.71) .aspx) :

Proprietà con valori di matrice

  

Dovresti usare le raccolte per evitare inefficienze del codice. Nel seguente esempio di codice, ogni chiamata alla proprietà myObj crea una copia dell'array. Di conseguenza, nel ciclo seguente verranno create 2n + 1 copie dell'array.

[Visual Basic]

Dim i As Integer
For i = 0 To obj.myObj.Count - 1
   DoSomething(obj.myObj(i))
Next i

[C#]
for (int i = 0; i < obj.myObj.Count; i++)
      DoSomething(obj.myObj[i]);

Oltre alla modifica da myObj [] a ICollection myObj, cos'altro consiglieresti? Ho appena realizzato che la mia app attuale sta perdendo memoria :(

Grazie;

EDIT: forzare C # a passare i riferimenti con ref (sicurezza a parte) migliorerebbe le prestazioni e / o l'utilizzo della memoria?

È stato utile?

Soluzione

No, non è perdita di memoria - sta solo facendo lavorare il Garbage Collector più duramente di quanto potrebbe. In realtà, l'articolo MSDN è leggermente fuorviante: se la proprietà creasse una nuova collezione ogni volta che veniva chiamata, sarebbe altrettanto brutta (per quanto riguarda la memoria) come con un array. Forse peggio, a causa del solito sovradimensionamento della maggior parte delle implementazioni di raccolta.

Se sai che un metodo / proprietà funziona, puoi sempre ridurre al minimo il numero di chiamate:

var arr = obj.myObj; // var since I don't know the type!
for (int i = 0; i < arr.Length; i++) {
  DoSomething(arr[i]);
}

o ancora più semplice, usa foreach :

foreach(var value in obj.myObj) {
  DoSomething(value);
}

Entrambi gli approcci chiamano la proprietà solo una volta. Il secondo è più chiaro dell'IMO.

Altri pensieri; chiamalo un metodo! cioè obj.SomeMethod () - questo imposta l'aspettativa che funzioni ed evita il indesiderato obj.Foo! = obj.Foo (che sarebbe il caso degli array) .

Infine, Eric Lippert ha un buon articolo su questo argomento .

Altri suggerimenti

Proprio come un suggerimento per coloro che non hanno utilizzato ReadOnlyCollection menzionato in alcune delle risposte:

[C#]

class XY
{
  private X[] array;

  public ReadOnlyCollection<X> myObj
  {
    get
    {
      return Array.AsReadOnly(array);
    }
  }
}

Spero che questo possa aiutare.

Ogni volta che ho proprietà che sono costose (come ricreare una raccolta su chiamata) documento la proprietà, affermando che ogni chiamata comporta un costo, oppure memorizzo nella cache il valore come campo privato. I getter di proprietà che sono costosi, dovrebbero essere scritti come metodi. In genere, provo a esporre le raccolte come IEnumerable anziché come array, costringendo il consumatore a utilizzare foreach (o un enumeratore).

Non farà copie dell'array a meno che non lo facciate. Tuttavia, semplicemente passare il riferimento a un array di proprietà privata di un oggetto ha alcuni effetti collaterali spiacevoli. Chiunque riceva il riferimento è sostanzialmente libero di fare tutto ciò che gli piace con l'array, compresa la modifica dei contenuti in modi che non possono essere controllati dal suo proprietario.

Un modo per impedire l'ingerenza non autorizzata con l'array è di restituire una copia del contenuto. Un altro (leggermente migliore) è restituire una raccolta di sola lettura.

Tuttavia, prima di fare una qualsiasi di queste cose dovresti chiederti se stai per dare troppe informazioni. In alcuni casi (in realtà, abbastanza spesso) è ancora meglio mantenere l'array privato e invece fornire metodi che operino sull'oggetto che lo possiede.

myobj non creerà un nuovo elemento se non ne crei esplicitamente uno. quindi per un migliore utilizzo della memoria ti consiglio di utilizzare la raccolta privata (Elenco o qualsiasi) ed esporre l'indicizzatore che restituirà il valore specificato dalla raccolta privata

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top