C#2008
我一直在研究这个问题,我仍然对一些问题感到困惑.我的问题如下
我知道如果你处理非托管资源,你只需要一个终结器.但是,如果您使用托管资源来调用非托管资源,您是否仍需要实现终结器?
但是,如果您开发一个不直接或间接使用任何非托管资源的类,您是否可以实现IDisposable该类,以便您的类的客户端可以使用'using statement'?
是否可以接受实现IDisposable,以便您的类的客户端可以使用using语句?
using(myClass objClass = new myClass())
{
// Do stuff here
}
Run Code Online (Sandbox Code Playgroud)我在下面开发了这个简单的代码来演示Finalize/dispose模式:
public class NoGateway : IDisposable
{
private WebClient wc = null;
public NoGateway()
{
wc = new WebClient();
wc.DownloadStringCompleted += wc_DownloadStringCompleted;
}
// Start the Async call to find if NoGateway is true or false
public void NoGatewayStatus()
{
// Start the Async's download
// Do other work here
wc.DownloadStringAsync(new Uri(www.xxxx.xxx));
}
private void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
// …Run Code Online (Sandbox Code Playgroud)我最近与同事讨论了Dispose实施的价值和类型IDisposable.
我认为即使没有非托管资源可以清理IDisposable,也应该尽快清理类型.
我的同事有不同的想法; 执行IDisposable,如果你没有任何非托管资源为你的类型,最终会被垃圾收集是没有必要的.
我的论点是,如果你有一个想要尽快关闭的ADO.NET连接,那么实现IDisposable并且using new MyThingWithAConnection()有意义.我的同事回答说,在封面下,ADO.NET连接是一种非托管资源.我对他回复的答复是,最终所有东西都是一种非托管资源.
我知道推荐的一次性模式,如果Dispose被调用,你可以免费使用托管和非托管资源,但是如果通过终结器/析构函数调用,则只有免费的非托管资源(前面有关于如何提醒消费者不正确使用您的IDisposable类型的博客)
所以,我的问题是,如果你有一个不包含非托管资源的类型,是否值得实现IDisposable?
我需要启动一个线程,但在线程实际运行后继续.现在我的代码看起来像:
splashthread.IsBackground = false;
splashthread.Start();
Thread.Sleep(100); // Wait for the thread to start
Run Code Online (Sandbox Code Playgroud)
我不喜欢这些伏都教睡眠(至少可以说),所以我正在寻找更好的方式来做上述事情.
有任何想法吗?
创建后我是否需要处理sqldatareader?
SqlDataReader reader;
---
---
---
reader.Close();
reader.Dispose();
Run Code Online (Sandbox Code Playgroud) 我正在使用C#EPPlus库来创建Excel文档.
ExcelWorksheet ws = pkg.Workbook.Worksheets.Add("Sheet1");
ws.Cells["E3"].Value = "Foo";
ws.Cells["F3"].Value = "Bar";
ws.Cells["F3"].Style.Font.Bold = true;
Run Code Online (Sandbox Code Playgroud)
该ws.Cells[]返回类型是ExcelRange具有Dispose()方法.我每次使用时都需要打电话ws.Cells[]吗?
就像是
ExcelWorksheet ws = pkg.Workbook.Worksheets.Add("Sheet1");
ExcelRange rng;
rng = ws.Cells["E3"];
rng.Value = "Foo";
rng.Dispose();
using (rng = ws.Cells["F3"])
{
rng.Value = "Bar";
rng.Style.Font.Bold = true;
}
Run Code Online (Sandbox Code Playgroud)
会是一个沉重的语法!
真的有必要吗?
虽然我已经编写了一段时间,但我真的只是进入了我所谓的中级编码器.所以我理解dispose()的原理,即释放为变量和/或资源保留的内存.我也发现有时使用EF我必须dispose()以便其他操作正常工作.我不明白的只是需要发布的内容,何时使用dispose().
例如,我们不处理变量,如字符串,整数或布尔值.但是在某个地方我们越过"一条线",我们使用的变量和/或资源需要被处理掉.我不明白这条线在哪里.
在知道何时使用dispose()时,是否有一个原则或几个广泛的原则适用?
我阅读了这些SO帖子(具体情况,更多关于如何而不是何时)但我不觉得我理解何时使用dispose()的基础知识.我看到一条评论询问是否在变量超出范围时释放内存,这引起了我的注意,因为直到我看到响应为否,它才会因为超出范围而被释放,我会想到当它超出范围时它会被释放.我不想成为第二个链接中的一个人称为"无能的开发者",虽然我认为这有点苛刻.我们中的一些人还在学习.
所以这就是为什么我的问题是"什么决定何时真正需要处置?"
我的问题是少一个多么多的一个时候.当然评论如何有用,但即使调用dispose()的方法是一个Using语句,我仍然需要知道什么时候.
编辑原始问题: 我知道这是一个很长的解释,标记为重复的评论笔记请求,这不是一个咆哮,我只是不知道如何确保我专注于我的精确问题.很多时候,我们只是匆匆走过我们问的方式.正如我在这篇长篇文章的最后提到的那样,在我们专注于我的问题后,我将编辑所有这些,假设我们到达那里.根据我所读到的内容,我认为这是一个重要的问题.
提议的"答案"帖子是一篇很棒的帖子,但并没有真正回答我的问题.CodeNotFound下面的评论也提供了一个很好的链接,但它也没有真正回答我的问题.我提供了有关这些帖子的评论,以尝试帮助改进我的确切问题:
我什么时候应该在.NET中处理我的对象?:第一个答案以评论开头
一次性对象表示持有CLR本质上不知道的有价值资源的对象.
不幸的是,我不明白" 一次性对象...... CLR本质上没有意识到 " 这一术语包括在内. 这就是我要问的问题.我怎么知道某件事是否属于我必须处理的范畴?我们一直在代码中定义要使用的东西.我们何时越过这条线并成为我需要处置的对象()?顺便说一句,我注意到那篇文章的作者从未标出答案.我不知道这是否意味着他不觉得这个问题得到了回答,或者他的跟进是否很差,但我希望我能够提炼一点我希望了解的内容.当你仔细观察答案时,他们并没有真正解决哪些对象需要开发人员处理它们的问题,或者我如何知道如何识别哪些对象.我只是不知道我创建的对象或事物需要我负责处理.我认为GC和其他条款发挥作用,但同样,这就是方法.显而易见的是,大多数经验丰富的专业开发人员都知道他们创建的东西何时需要被处理掉.我不明白怎么知道那.
正确使用IDisposable界面:显然是一个流行的答案(1681 upvotes),但明确的答案开始于
Dispose的目的是释放非托管资源".
好的,但我的问题是如何通过查看它是非托管资源的东西来了解?我不理解以下说明如何应用到什么需要处置.
如果你在.NET框架中找到它,那么它就是托管的.如果你自己去探索MSDN,它是无人管理的 ...你现在负责清理它."
我不明白如何使用这种类型的解释来分类我需要处理的东西()和我不需要的东西..net框架中有各种各样的东西; 如何分离出需要我处理它们的东西?我该怎么看我告诉我我对此负责?
在那之后,这个答案就在约大篇幅讲了如何处置(),但我仍然停留在背什么需要处置.为了让这个话题进一步复杂化,该作者后来说:"现在我们将...
摆脱非托管资源(因为我们必须),和
摆脱托管资源(因为我们想要帮助)
所以现在我需要考虑处理一组使用内存的全新对象,我不知道它们是什么.该答案的作者后来说
对于任何喜欢这种答案风格的人(解释原因,如何变得明显)......
我理解作者是在暗示其他文章,但作者的建议是理解"为什么"使得"如何"显而易见并不合法,因为对一个人来说显而易见的事情对另一个人来说并不总是显而易见的.甚至在那时,作者更多地关注为什么以及如何,并且我的问题是什么时候,意味着什么需要被处理(),而不是当我完成它时.我知道当我做完事情时,我只是不知道 …
析构函数应该只释放对象所持有的非托管资源,并且不应该引用其他对象.如果您只有托管引用,则不需要(也不应该)实现析构函数.您希望这仅用于处理非托管资源.因为拥有析构函数需要一些成本,所以你应该只在消耗有价值的非托管资源的方法上实现它.
文章没有深入讨论这个问题,但在C#中使用析构函数会涉及哪些成本?
注意:我知道GC以及在可靠的时候没有调用析构函数的事实,除此之外,还有什么吗?
我新客户所在的代码审查清单如下 -
实现Dispose和Finalize的类应该在Dispose实现中调用GC.SupressFinalize
为什么?
它是否应该读取为实现IDisposable接口的类应该在Dispose实现中调用GC.SupressFinalize?
或者我错过了一些愚蠢的东西?
.net garbage-collection idisposable finalizer suppressfinalize
c# ×7
.net ×5
finalizer ×4
idisposable ×4
dispose ×2
destructor ×1
epplus ×1
excel ×1
finalization ×1
vb.net ×1