2010-12-10 54 views
2

我一直認爲通過在using之前聲明var將允許它在using之內分配,然後我仍然可以讀取它之外的變量。原來我不能:-)在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 

任何辦法讓它不停止使用using

完整的測試方法工作:

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; 
    } 

回答

3

喬爾龍多在他的回答中指出,集合是被CLE因爲檔案正在處理中。但是,將其包裝在ReadonlyCollection中將不起作用,因爲它不會複製包裝列表。您需要手動創建這個副本:

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

工作:-) – MadBoy 2010-12-10 20:10:01

+0

是的。在這種情況下,檢查文檔和我的「新」理論肯定不起作用。這好多了。 – 2010-12-10 20:10:26

6

複製archive.Volumes,而不是隻具有參考集合它。然後,在使用結束時處理歸檔時,您的收藏將不會被處置。

+0

你的意思是複製它? – MadBoy 2010-12-10 19:53:22

+0

我改變它,並且在使用之外它仍然變爲0 ..我已經添加了我用於我的帖子的示例。 – MadBoy 2010-12-10 20:01:11

2

你完全可以從變量中讀取數據。在明確的賦值方面沒有問題,否則會產生編譯時錯誤。例如,這很好:

using System; 
using System.IO; 

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

這絕對沒問題。現在

如果SevenZipArchive返回ReadOnlyCollection<string>,我通常預期仍然有效歸檔本身被設置後。然而,ReadOnlyCollection<T>只是另一個集合的包裝......並且如果通過處置archive使該集合失效,那肯定會解釋一些事情。

不幸的是,Joel建議的複製方法是創建另一個包裝器 - 它會詢問第一個包裝器的數量,然後詢問原始(無效)的收集器。

這裏有一個方法應該工作:

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; 
} 

注意額外的呼叫ToList()。這將強制收集複製到第一個List<string> ...真正複製,而不僅僅是創建一個包裝。

當然,如果你不介意,如果該方法返回一個列表,你可以只使用:

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; 
} 

...然後當你不需要額外的診斷:

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

(我假設你正在使用.NET 3.5或更高版本,順便說一句,使用ToList擴展方法。)

+0

那麼爲什麼我在使用內部時count = 10,當外部變爲0時呢? – MadBoy 2010-12-10 19:58:38

+0

我怎樣才能防止它被丟棄而不使用處置? – MadBoy 2010-12-10 20:08:38

+0

@MadBoy:查看我的編輯。 – 2010-12-10 20:11:00

1

我想類似的東西,我獲得通過的測試:

[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

您正在使用不同的SevenZipLib。我使用SevenZipLib,你似乎正在使用SevenZipSharp,它似乎行事不同。我的行爲似乎像Jon說的那樣。 – MadBoy 2010-12-10 20:14:45

+0

是的,看看裏面發生了什麼會很有趣 – 2010-12-10 20:23:55

0

的問題是,你引用的字段是存檔的一部分。歸檔對象由於使用閉包而不存在。

你可以克隆使用的內部值,它會給你一個列表的副本,而不是對列表值的引用,並且可以完成這項工作。

相關問題