在C#中使用并使用变量赋值内部使用
我一直认为通过在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;
}
乔尔龙多在他的回答中指出,集合是被CLE因为档案正在处理中。但是,将其包装在ReadonlyCollection
中将不起作用,因为它不会复制包装列表。您需要手动创建这个副本:
ReadOnlyCollection<string> collection;
using (var archive = new SevenZipArchive(varRarFileName))
{
collection = new ReadOnlyCollection<string>(archive.Volumes.ToList());
}
你完全可以从变量中读取数据。在明确的赋值方面没有问题,否则会产生编译时错误。例如,这很好:
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
扩展方法。)
我想类似的东西,我获得通过的测试:
[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);
}
您正在使用不同的SevenZipLib。我使用SevenZipLib,你似乎正在使用SevenZipSharp,它似乎行事不同。我的行为似乎像Jon说的那样。 – MadBoy 2010-12-10 20:14:45
是的,看看里面发生了什么会很有趣 – 2010-12-10 20:23:55
的问题是,你引用的字段是存档的一部分。归档对象由于使用闭包而不存在。
你可以克隆使用的内部值,它会给你一个列表的副本,而不是对列表值的引用,并且可以完成这项工作。
工作:-) – MadBoy 2010-12-10 20:10:01
是的。在这种情况下,检查文档和我的“新”理论肯定不起作用。这好多了。 – 2010-12-10 20:10:26