2010-01-29 11 views
6

J'ai une classe, dont les instances doivent être éliminées. J'ai aussi plusieurs classes qui produisent ces instances, soit individuellement, soit en listes.Devrais-je avoir des méthodes qui renvoient des listes d'instances jetables?

Devrais-je retourner IList<MyClass> à partir de mes méthodes ou devrais-je créer une classe MyClassCollection qui est également jetable et la retourner à la place?

EDIT:

Ma principale raison de demander est que j'ai fini par le faire beaucoup:

IList<MyObject> list = GetList(); 
foreach(MyObject obj in list) 
{ 
    //do something 
    obj.Dispose(); 
} 

et il semble que je serais mieux faire:

using (IList<MyObject> list = GetList()) 
{ 
    foreach(MyObject obj in list) 
    { 
    //do something 

    } 
} 
+0

Votre premier exemple dispose des objets dès qu'ils ne sont plus nécessaires, mais le second exemple les maintient en vie jusqu'à ce que l'itération entière soit terminée. C'est deux manières différentes de manipuler les objets, et vous devez choisir la méthode que vous voulez utiliser en fonction de ce qui est le plus approprié. –

Répondre

1

Une classe de conteneur serait probablement plus propre dans ces cas. Vous pouvez ensuite continuer à utiliser les classes de collection standard et vous devez être plus explicite quant au moment où les éléments devront être éliminés à la fin.

public class ListScope : IDisposable 
{ 
    private IList list; 
    public ListScope(IList list) 
    { 
     this.list = list; 
    } 

    #region IDisposable Members 

    public void Dispose() 
    { 
     foreach (object o in this.list) 
     { 
      IDisposable disposable = (o as IDisposable); 
      if (disposable != null) 
        disposable.Dispose(); 
     } 
    } 

    #endregion 
} 

Vous pouvez utiliser comme:

using (new ListScope (list)) 
{ 
    // Do stuff with list 
} 
+0

Pourquoi utilisez-vous 'if (o est IDisposable) {(o comme IDisposable) .Dispose(); } '? Pourquoi ne pas simplement utiliser 'o comme IDisposable' puis tester pour null? – thecoop

+0

@thecoop Je ne vois vraiment pas ce que j'obtiendrais de cette approche. Id doit soit utiliser une variable temp ou faire si ((o comme IDisposabe)! = Null) {(o comme IDisposable) .Dispose()}. Je pense que cette façon est plus propre, mais n'hésitez pas à utiliser non plus, je ne pense pas qu'il y ait vraiment beaucoup de choses dedans. :) –

+0

Je pense qu'un double (o comme IDisposable) coïncide avec une règle d'analyse de code statique, en disant que vous devriez créer une variable pour éviter les jets répétés inutiles. (Pas vrai?) – peSHIr

2

Cela dépend de la façon dont vous allez les utiliser, les deux semblent des options raisonnables. Si vous savez que vous devrez disposer de tous les objets en même temps, alors rendre la liste jetable a du sens, mais si les objets peuvent avoir des durées de vie différentes, je retournerai simplement une liste ordinaire.

Peut-être que vous pourriez faire un IDisposableList<T> générique avec une contrainte sur T where T : IDisposable et que votre classe implémente IDisposable en appelant Dispose sur tous ses éléments? Vous pouvez ensuite réutiliser cette classe pour tous vos différents types IDisposable.

+0

édité ma question pour donner des exemples de ce que je veux faire –

+0

@bebop: Je pense que si vous choisissez la liste qui dispose, il est peut-être un peu plus pratique maintenant pour votre situation actuelle, mais vous laissez entendre que votre client doit toujours disposer les objets simultanément. Y a-t-il une raison fondamentale pour laquelle les objets doivent être éliminés en même temps, et cela pourrait-il être modélisé d'une manière différente en ayant une ressource à disposer à la place? Votre situation me rappelle un peu les connexions et les transactions, ou un fichier avec beaucoup de lecteurs. Peut-être pourriez-vous utiliser ces classes comme source d'inspiration pour votre design? –

2

Il appartient entièrement au code client d'appeler votre méthode Dispose(). Seulement il sait quand il est fait en utilisant les objets. Vous ne pouvez rien y faire car vous ne savez pas à quoi ressemblera ce code. Créer des objets de liste qui disposent de leurs éléments n'est pas une bonne idée. Le framework ne contient aucun objet de collection qui le fait. Vous allez juste confondre le programmeur de code client.

+1

hmm intéressant. Je suppose qu'il peut y avoir des situations où certains éléments de la liste sont retournés à une autre méthode, et puis la disposition de la liste pourrait causer des problèmes –

1

Vous pouvez également utiliser une extension si vous voulez:

static class Extensions 
{ 
public static void DoStuffAndDisposeElements<T> (this List<T> list, Action<T> action) 
{ 
     list.ForEach (x => { action (x); 
       IDisposable disposable = (x as IDisposable); 
       if (disposable != null) 
        disposable.Dispose(); 

     }); 
} 


} 

que vous pourriez appeler par:

getList().DoStuffAndDisposeElements (x => doStuff(x)); 

Non sûr combien vous en retireriez, mais il y a y avoir des situations où il serait utile;)

+0

.net 2.0, mais merci pour la suggestion –

3

Il peut être plus facile de générer une séquence des éléments (IEnumerable<T>) plutôt qu'une liste - il existe des moyens que vous pouvez faire toute la durée de chaque égalité dans le iterator, de sorte que:

  • vous avez seulement un à la fois (je suppose qu'ils sont chers)
  • ils obtiennent disposés quand leur temps est écoulé
  • tous se disposés, même dans l'erreur

Ceci est un sujet que j'ai exploré here en utilisant LINQ, mais il y a d'autres façons aussi, si votre source est (ou peut être) une séquence.