Question

J'ai une classe qui lit les données d'un flux de fichiers et écrit à un autre. Je suis préoccupé par la fermeture des flux après que le traitement est terminé en closeFiles ().

Comment réagiriez-vous la possibilité que le départir d'un cours d'eau peut jeter une exception arrêter la Éliminez de l'autre flux d'être appelé.

Dois-je me appelle à proximité et sur les cours d'eau Éliminez ou un seul?

Qu'est-ce qui se passe si je prends des erreurs des cours d'eau et dispose ensuite de continuer avec le déplacement et la suppression des fichiers comme indiqué dans lastOperation ()?

Dans un monde parfait, je voudrais utiliser une instruction à l'aide d'une liste d'initialisation de style c ++ mais je suis sûr que ce ne peut en c #.

Modifier : merci pour les gars réponses rapides. Donc ce que je devrais faire est de tirer IDisposable puis modifiez le constructeur et ajouter les deux méthodes comme celui-ci disposant:

    ~FileProcessor()
    {
        Dispose(true);
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    private void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            if (disposing)
            {
                sw.Flush();
            }
            closeFiles();
            disposed = true;
        }
    }

Ceci est essentiellement ce que je fais:

class FileProcessor
{
    private string in_filename;
    private string out_filename;
    private StreamReader sr;
    private StreamWriter sw;
    bool filesOpen = false;

    public FileProcessor(string filename)
    {
        in_filename = filename; 
        out_filename = filename + ".out";
        openFiles();
    }

    ~FileProcessor()
    {
        closeFiles();
    }

    private void openFiles()
    {
        sr = new StreamReader(in_filename);
        sw = new StreamWriter(out_filename);
        filesOpen = true;
    }

    private void closeFiles()
    {
        if (filesOpen)
        {
            sr.Close();
            sw.Close();
            sr.Dispose();
            sw.Dispose();
            filesOpen = false;
        }
    }

    /* various functions to read, process and write to the files */

    public void lastOperation()
    {
        closeFiles();
        File.Delete( in_filename );
        Directory.Move(out_filename, outdir + out_filename);
    }
}
Était-ce utile?

La solution

Votre classe FileProcessor ne devrait pas avoir un destructor. Il est inutile, mais il est cher.

Il devrait avoir un Dispose() (et implémenter l'interface IDisposable) pour appeler closeFiles ().

Et comme @marcelo répondit Stream.Dispose () ne doit pas jeter. Vous pouvez compter sur cela pour les classes de la BCL.

Mais vous devriez vérifier chaque lecteur / enregistreur pour null, dans le cas où le premier a ouvert, mais le second a échoué:

if (sr != null) sr.Dispose();
if (sw != null) sw.Dispose();

Votre filesOpen ne peut pas couvrir à la fois.

Autres conseils

Je pense qu'il est une bonne pratique d'avoir votre classe implémente l'interface IDisposable si vous utilisez l'objet IDisposable à l'intérieur.

Ensuite, vous devez vous assurer que, dans votre mise en œuvre de Dispose(), ne jette pas des exceptions. Si chaque objet vous fait Éliminez cette garantie, votre client sera en sécurité.

méthodes Dispose ne devraient jamais jeter des exceptions. Il y a même un outil d'analyse de code avertissement pour cela.

En C #, using ne existe. L'objet fourni à l'instruction à l'aide doit implémenter l'interface IDisposable. Cette interface fournit la méthode Dispose, qui devrait libérer les ressources de l'objet.

Si votre StreamReader et StreamWriter mettre en œuvre IDisposable, vous pouvez les mettre dans un bloc à l'aide, et ils seront éliminés proprement lorsque vous avez terminé avec eux.

using(var sr = new StreamReader(in_filename)) {
    // Perform reader actions
}
// Reader will now be disposed.
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top