失去参数值

我正在编写一些东西,我正在传递一个string给构造函数。 生成string的方式没有任何变化,但是(当我在Visual Studio社区中运行debugging工具时)第一次失去了该值,但在其他时间显示了一个值。 间歇性地,该值报告该string为空,或者它应该是的值。

现在,我真的不知道如何logging我正在做什么,所以这里是基础知识。

第一部分是TempDir的定义。 我使用这些临时目录作为testing目录,当TempDir(和testing)超出范围时,会自动自杀,并删除内容。

最后,工作,没有损失的价值版本

public class TempDir : IDisposable { private readonly string _path; public string ActiveDirectory => _path.Substring(_path.LastIndexOf('/') + 1, (_path.Length - _path.LastIndexOf('/') - 1)); public string Path { get { return _path; } } public TempDir(string path) : this(path, false) { } public TempDir(string path, bool KillExisting) { _path = path; if(!KillExisting) return; if(Directory.Exists(_path)) Directory.Delete(_path); } public void Dispose( ) { if(System.IO.Directory.Exists(_path)) Directory.Delete(_path, true); } public static implicit operator String(TempDir dir) => dir._path; } 

现在,这是我发送给构造函数的代码。 TempDir的ActiveDirectory被发送到一个构造函数,其中NameOfThing应该是第一个参数的结果,第二个参数也是一个string。 第一个是间歇性工作,第二个总是工作。

 TempDir dir = new TempDir(Environment.GetFolderPath(Environment.SpecialFolders.LocalApplicationData) + "/First/Second/NameOfThing") 

这是第一次运行 这是之后立即运行

我对此非常失望,从我所知道的情况来看,我认为一条线索可能会在我不知情的情况下改变我的一些东西

编辑:

我现在可以“可靠地”让它通过每一次,但是我必须慢慢地走过每一行代码。 每次运行都没有任何问题,每次运行都会失败,但每次debugging都会慢慢debugging。

代码构buildTempDir:

 protected static string PackagesLocation = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "/Sloth/Notes/"; protected static TempDir TestPackLoc = new TempDir(PackagesLocation + "NPackageTests"); protected static NPackage TestPack = new NPackage(TestPackLoc.ActiveDirectory); 

testing方法创build页面

 [TestMethod] public void GeneratesLayoutAndResourcesDirectory( ) { string key = "GeneratesLayoutAndResourcesDictionary"; TestPack.CreatePage(key); if(!Directory.Exists(TestPackLoc + "/" + key + "/res") && !Directory.Exists(TestPackLoc + "/" + key + "/layout.xml")) Assert.Fail( ); } 

好的,所以我认为丢失值的行为是因为C#不恰当地调用了垃圾回收器。 @mason提到,对于TempDirtypes,而不是实现析构函数,我应该实现IDisposable。 现在,它工作可靠,一贯。 我不知道为什么实现析构函数这样做,但交换IDisposable的作品就好了。

信贷的解决scheme去@mason

析构函数在这里并不是真的需要。 IDisposable模式可以用来代替。 除了实现接口之外,还有更多的事情需要在使用IDisposable任何对象中正确处理对象。 你可以实现一个using语句 。

 using(var tempDir = new TempDir(arguments)) { //you can use tempDir inside here } //tempDir's Dispose method is automatically called here //since tempDir is out of scope here, the directory will have been deleted already 

任何时候,一个对象实现IDisposable,你应该把它包装在上面的using语句中,或者在finally块中调用它的Dispose方法,以确保它被正确地移除。 以下是try / catch / finally版本的内容:

 TempDir tempDir = null; try { tempDir = new TempDir(arguments); //now you can use tempDir here } catch(Exception ex) { //log the exception. Optionally rethrow. Do not leave catch block empty } finally { if(tempDir != null) { tempDir.Dispose(); } } 

大多数时候我更喜欢using块,因为它使变量的范围更清晰。

可以使用析构函数来确保如果有人忘记调用Dispose或将对象包装在非托管资源(目录)被正确清理的using块中。

 public class TempDir : IDisposable { private readonly string _path; public string ActiveDirectory => _path.Substring(_path.LastIndexOf('/') + 1, (_path.Length - _path.LastIndexOf('/') - 1)); public string Path => _path; public TempDir(string path) : this(path, false) { } public TempDir(string path, bool KillExisting) { if(string.IsNullOrEmpty(path)) { throw new ArgumentException($"{nameof(path)} cannot be null or empty."); } _path = path; if(KillExisting && Directory.Exists(_path)) { Directory.Delete(_path); } //why not call Directory.CreateDirectory(_path) here? } public void Dispose( ) { Cleanup(); } ~TempDir() { Cleanup(); } private void Cleanup() { if(Directory.Exists(_path)) { Directory.Delete(_path, true); } } public static implicit operator String(TempDir dir) => dir._path; } 

无需手动将对象设置为null因为垃圾回收器将处理为您取消分配内存。

你没有正确地封装你的私有变量。 这可能是因为你在你的类之外使用了公共的_path变量,并且无意中把它设置为了别的东西。

TempDir类的改进版本可能如下所示:

 public class TempDir { private string _path; public TempDir(string path) : this(path, false) { } public TempDir(string path, bool killExisting) { _path = path; if (!killExisting) return; if (Directory.Exists(_path)) Directory.Delete(_path); } public string Path => _path; public string ActiveDirectory => _path.Substring(_path.LastIndexOf('/') + 1, _path.Length - _path.LastIndexOf('/') - 1); ~TempDir() { if (System.IO.Directory.Exists(_path)) Directory.Delete(_path, true); _path = null; } public static implicit operator string(TempDir dir) { return dir._path; } }