2010-09-01 5 views
2

j'ai un objet qui utilise des ressources natives sous-jacentes, et a un pointeur vers l'instance suivante, que j'itérer semblable à:Comment se débarrasser d'un objet itéré via sa propriété Next?

MyObject begin = null; 

try 
{ 
    begin = GetFirst(); 

    while (begin != null) 
    { 
     MyObject next = begin.Next(); 
     // do something with begin 
     begin.Dispose(); 
     begin = next; 
    } 
} 
finally 
{  
    if (begin != null) 
    { 
     begin.Dispose(); 
    } 
} 

Je reçois le problème d'analyse de code:

CA2202 : Microsoft.Usage: l'objet 'begin' peut être disposé plus d'une fois dans la méthode 'x()'. Pour éviter de générer une exception System.ObjectDisposedException, vous ne devez pas appeler Dispose plus d'une fois sur un objet.

Une idée de comment je peux me débarrasser de cette erreur sans la supprimer?

+0

Est-ce que serrer un 'begin = null;' juste après la ligne 'begin.Dispose()' s'en occuper? – kbrimington

+0

@kbrimington: Non, c'était aussi ma première pensée.Pas de chance :( – esac

+0

Je voudrais examiner si le processus d'itération entier pourrait être encapsulé dans une classe de générateur de niveau supérieur, qui serait alors responsable du nettoyage après le résultat entier de la génération des éléments. –

Répondre

4

Il me semble que votre dernier bloc de code est inutile. Si begin != null, alors votre boucle while aurait dû continuer, non?

MISE À JOUR: Il semble que vous essayez de vous assurer que la dernière valeur obtenue pour begin est éliminée en cas d'exception. Essayez ceci:

MyObject begin = GetFirst(); 

while (begin != null) 
{ 
    MyObject next; 
    using (begin) 
    { 
     next = begin.Next(); 
     // do something with begin 
    } 

    begin = next; 
} 

Notez que la suggestion ci-dessus, il pourrait effectivement se produire encore que vous vous retrouvez avec un objet non aliéné: la dernière valeur attribuée à next, avant la fin du bloc using. Ce scénario n'a pas été couvert dans votre question initiale, donc je ne l'ai pas abordé dans la suggestion ci-dessus. C'est quelque chose à considérer, cependant, si c'est un problème potentiel.

0

Il semble que l'analyse de code considère qu'il est possible qu'une exception se produise pendant la méthode Dispose(). Si tel était le cas, vous entreriez dans le bloc finally avec une référence déjà-albeit-non-null déjà disposée à begin.

Notez que je ne préférerais cette approche à @ Dan si vous prévoyez d'envelopper l'appel à begin.Dispose() dans le piégeage et la gestion des erreurs supplémentaires. IMO, la solution de Dan est plus élégante.

Voici une approche try-finally qui supprime l'avertissement:

MyObject begin = GetFirst(); 
MyObject next = null; 

while (begin != null) 
{ 
    try 
    { 
     next = begin.Next(); 
     // do something with begin 
    } 
    finally 
    { 
     begin.Dispose(); 
     begin = next; 
    } 
} 
0

Vous avez évidemment un mécanisme pour identifier le premier élément de la chaîne, peut-être un autre objet ou une statique qui stocke le premier élément ?

Que diriez-vous dans votre code qui appelle à l'origine disposer:

GetFirst().Dispose(); 

la seule responsabilité de la méthode dispose est de disposer l'élément en cours et des enfants:

public void Dispose() 
{ 
    if (Next() != null) 
    { 
     Next().Dispose(); 
    } 
} 

Cela permet d'éliminer tout besoin de boucler dans la méthode d'élimination. Je voudrais également jeter un oeil à la dispose pattern

Questions connexes