Question

Selon [MSDN: Règles d'utilisation de l'ensemble] ( http://msdn.microsoft.com/en-us/library/k2604h5s (VS.71) .aspx) :

Propriétés valides du tableau

  

Vous devez utiliser des collections pour éviter les inefficacités du code. Dans l'exemple de code suivant, chaque appel de la propriété myObj crée une copie du tableau. En conséquence, 2n + 1 copies du tableau seront créées dans la boucle suivante.

[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]);

À part le changement de myObj [] à ICollection myObj, que recommanderiez-vous d'autre? Je viens de me rendre compte que mon application actuelle perd de la mémoire: (

Merci;

EDIT: Forcer C # à passer des références avec référence (côté sécurité) améliorerait les performances et / ou l’utilisation de la mémoire?

Était-ce utile?

La solution

Non, ce n'est pas une fuite de mémoire - cela ne fait que rendre le ramasse-miettes plus puissant qu'il ne le pourrait. En fait, l'article MSDN est légèrement trompeur: si la propriété créait une nouvelle collection à chaque appel, elle serait tout aussi mauvaise (en termes de mémoire) que pour un tableau. Peut-être pire, en raison du surdimensionnement habituel de la plupart des implémentations de collection.

Si vous savez qu'une méthode / propriété fonctionne, vous pouvez toujours réduire le nombre d'appels:

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

ou encore plus simple, utilisez foreach :

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

Les deux approches appellent la propriété une seule fois. La seconde est plus claire à l’OMI.

Autres pensées; nommez-le une méthode! c.-à-d. obj.SomeMethod () - cela définit l'espoir que cela fonctionne et évite les indésirables obj.Foo! = obj.Foo (ce qui serait le cas pour les tableaux). .

Enfin, Eric Lippert a un bon article sur ce sujet .

Autres conseils

Juste comme un indice pour ceux qui n'ont pas utilisé la ReadOnlyCollection mentionnée dans certaines des réponses:

[C#]

class XY
{
  private X[] array;

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

J'espère que cela pourrait aider.

Chaque fois que j'ai des propriétés coûteuses (comme recréer une collection sur appel), je documente la propriété en indiquant que chaque appel implique un coût, ou bien je cache la valeur en tant que champ privé. Les accesseurs de propriétés qui sont coûteux doivent être écrits en tant que méthodes. En général, j'essaie d'exposer les collections sous la forme IEnumerable plutôt que sur des tableaux, ce qui oblige le consommateur à utiliser foreach (ou un énumérateur).

Il ne fera pas de copies du tableau à moins que vous ne le fassiez. Cependant, le simple fait de passer la référence à un tableau appartenant à un objet appartenant à un particulier a des effets secondaires désagréables. Quiconque reçoit la référence est fondamentalement libre de faire ce qu'il veut avec le tableau, y compris en modifiant le contenu de manière que son propriétaire ne puisse pas contrôler.

Un moyen d'éviter toute ingérence non autorisée dans le tableau consiste à renvoyer une copie du contenu. Une autre solution (légèrement meilleure) consiste à renvoyer une collection en lecture seule.

Néanmoins, avant de faire l’une de ces choses, vous devriez vous demander si vous êtes sur le point de donner trop d’informations. Dans certains cas (en fait, assez souvent), il est même préférable de garder le tableau privé et de laisser plutôt fournir des méthodes qui fonctionnent sur l'objet qui le possède.

myobj ne créera pas de nouvel élément sauf si vous en créez explicitement un. donc, afin de mieux utiliser la mémoire, je recommande d’utiliser une collection privée (List ou any) et d’exposer l’indexeur qui renvoie la valeur spécifiée à partir de la collection privée

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top