2010-12-10 21 views
2

J'ai toujours pensé qu'en déclarant var avant que le using lui permette d'être assigné à l'intérieur de using et que je puisse encore lire une variable en dehors de celle-ci. Il s'avère que je ne peux pas :-)Utiliser et obtenir une variable affectée à l'intérieur en utilisant C#

 ReadOnlyCollection<string> collection; 
     using (var archive = new SevenZipArchive(varRarFileName)) { 
      collection = archive.Volumes; 
      MessageBox.Show(collection.Count.ToString()); // Output 10 
     } 
     MessageBox.Show(collection.Count.ToString()); // output 0 

Toute façon de le faire fonctionner sans arrêter d'utiliser using

méthode d'essai complète:

private ReadOnlyCollection<string> ExtractRar(string varRarFileName, string varDestinationDirectory) { 
     ReadOnlyCollection<string> collection; 
     using (var archive = new SevenZipArchive(varRarFileName)) { 
      collection = new ReadOnlyCollection<string>(archive.Volumes); 
      MessageBox.Show(collection.Count.ToString()); // output 10 


     } 
     MessageBox.Show(collection.Count.ToString()); // output 0 
     return collection; 
    } 

Répondre

3

Comme Joel Rondeau souligne dans sa réponse, la collection est cle au fur et à mesure que les archives sont éliminées. Toutefois, l'envelopper dans un ReadonlyCollection ne fonctionnera pas car cela ne copie pas la liste enveloppée. Vous devez créer cette copie manuellement:

ReadOnlyCollection<string> collection; 
using (var archive = new SevenZipArchive(varRarFileName)) 
{ 
    collection = new ReadOnlyCollection<string>(archive.Volumes.ToList()); 
} 
+0

Cela a fonctionné :-) – MadBoy

+0

Oui. La documentation vérifiée et ma «nouvelle» théorie ne fonctionneront certainement pas dans ce cas. Ceci est vraiment mieux. –

6

Copy archive.Volumes au lieu de simplement avoir la référence de collecte il. Ensuite, lorsque l'archive est éliminée à la fin de l'utilisation, votre collection n'aura pas été éliminée.

+0

Que voulez-vous dire par le copier? – MadBoy

+0

Je l'ai changé pour cela et il va encore 0 quand en dehors de l'utilisation .. J'ai ajouté un exemple de ce que j'utilise à mon poste. – MadBoy

2

Vous pouvez toujours lire dans la variable. Il n'y a pas de problème en termes d'affectation définie, ou vous obtiendrez une erreur de compilation. Par exemple, c'est bon:

using System; 
using System.IO; 

class Test 
{ 
    static void Main() 
    { 
     string x; 
     using (new MemoryStream()) 
     { 
      x = "hello"; 
     } 
     Console.WriteLine(x); 
    } 
} 

C'est tout à fait correct.

Maintenant, si SevenZipArchive retourne un ReadOnlyCollection<string>, je serais habituellement pense que pour être encore valide après l'archive elle-même est disposé. Cependant, ReadOnlyCollection<T> est simplement un emballage autour d'une autre collection ... et si cette collection est invalidée en disposant de archive, cela expliquerait certainement les choses. Malheureusement, la méthode suggérée par Joel pour copier la collection crée seulement un autre wrapper - qui demandera le premier wrapper pour le comptage, demandant à son tour la collection originale (invalidée).

est ici une approche qui devrait fonctionner:

private ReadOnlyCollection<string> ExtractRar(string varRarFileName, 
               string varDestinationDirectory) { 
    ReadOnlyCollection<string> collection; 
    using (var archive = new SevenZipArchive(varRarFileName)) { 
     collection = new ReadOnlyCollection<string>(archive.Volumes.ToList()); 
     MessageBox.Show(collection.Count.ToString()); // output 10 
    } 
    MessageBox.Show(collection.Count.ToString()); // output 0 
    return collection; 
} 

Notez l'appel supplémentaire à ToList(). Cela va forcer la collection à être copiée sur un List<string> d'abord ... vraiment copié, pas seulement en créant un wrapper.

Bien sûr, si vous ne me dérange pas vraiment si la méthode retourne une liste, vous pouvez simplement utiliser:

private List<string> ExtractRar(string varRarFileName, 
           string varDestinationDirectory) { 
    List<string> collection; 
    using (var archive = new SevenZipArchive(varRarFileName)) { 
     collection = archive.Volumes.ToList(); 
     MessageBox.Show(collection.Count.ToString()); // output 10 
    } 
    MessageBox.Show(collection.Count.ToString()); // output 0 
    return collection; 
} 

... et puis quand vous n'avez pas besoin des diagnostics supplémentaires:

private List<string> ExtractRar(string varRarFileName, 
           string varDestinationDirectory) { 
    using (var archive = new SevenZipArchive(varRarFileName)) { 
     return archive.Volumes.ToList(); 
    } 
} 

(je suppose que vous utilisez .NET 3.5 ou supérieur, en passant, d'utiliser la méthode d'extension ToList.)

+0

Eh bien alors pourquoi ai-je le compte = 10 quand à l'intérieur de l'utilisation, et quand il passe à 0? – MadBoy

+0

Comment puis-je l'empêcher d'être éliminé, sauf pour ne pas l'utiliser? – MadBoy

+0

@MadBoy: Voir mes modifications. –

1

J'ai essayé quelque chose de similaire et je reçois un test de passage:

[Test] public void CollectionCountShouldBeGreaterThanZero() { 
    // arrange 
    string tempDir = Path.GetTempPath(); 
    var fileInfo = new FileInfo(tempDir + Path.DirectorySeparatorChar + "test.zip"); 
    File.WriteAllBytes(fileInfo.FullName, Resources.TestZipFile); 

    SevenZipBase.SetLibraryPath(@"c:\7z.dll"); 

    // act 
    ReadOnlyCollection<string> collection; 
    using(var archive = new SevenZipExtractor(fileInfo.FullName)) 
    collection = archive.ArchiveFileNames; 

    // assert 
    Assert.IsTrue(collection.Count > 0); 
} 
+0

Vous utilisez différents SevenZipLib. J'utilise SevenZipLib et vous semblez utiliser SevenZipSharp qui semble agir différemment. Et le mien semble se comporter comme Jon dit. – MadBoy

+0

Oui, il serait intéressant de regarder à l'intérieur pour voir ce qui se passe –

0

Le problème est que le champ que vous faites référence fait partie des archives. L'objet archive n'existe pas à ce moment à cause de l'utilisation de la fermeture.

Vous pourriez cloner les valeurs à l'intérieur de l'utilisation qui vous donnerait une copie de la liste au lieu d'une référence aux valeurs de la liste et qui ferait le travail.