c# – 何时需要dispose()的规则是什么?
虽然我已经编写了一段时间,但我真的只是进入了我所谓的中级编码器.所以我理解dispose()的原理,即释放为变量和/或资源保留的内存.我也发现有时使用EF我必须dispose()才能使其他操作正常工作.我不明白的只是需要发布的内容,何时使用dispose().
例如,我们不处理变量,如字符串,整数或布尔值.但是在某个地方我们越过“一条线”,我们使用的变量和/或资源需要被处理掉.我不明白这条线在哪里. 在知道何时使用dispose()时,是否有一个原则或几个广泛的原则适用? 我读了这些SO帖子(a specific situation,more about how rather than when),但我不觉得我理解知道何时使用dispose()的基础知识.我看到一条评论询问是否在变量超出范围时释放内存,这引起了我的注意,因为直到我看到响应为否,它才会因为超出范围而被释放,我会想到当它超出范围时它会被释放.我不想成为第二个链接中的一个人称为“无能的开发者”,虽然我认为这有点苛刻.我们中的一些人还在学习. 所以这就是为什么我的问题是“什么时候确定需要处置?”? 我的问题不再那么多,何时.当然评论如何有用,但即使调用dispose()的方法是一个Using语句,我仍然需要知道什么时候. 编辑原始问题:我知道这是一个很长的解释,标记为重复的评论笔记请求,这不是一个咆哮,我只是不知道如何确保我专注于我的精确问题.很多时候,我们只是匆匆走过我们问的方式.正如我在这篇长篇文章的最后提到的那样,在我们专注于我的问题后,我将编辑所有这些,假设我们到达那里.根据我所读到的内容,我认为这是一个重要的问题. 提议的“答案”帖子是一篇很棒的帖子,但并没有真正回答我的问题. CodeNotFound下面的评论也提供了一个很好的链接,但它也没有真正回答我的问题.我提供了有关这些帖子的评论,以尝试帮助改进我的确切问题: When should I dispose my objects in .NET?:第一个答案以评论开头
不幸的是,我不明白“一次性对象…… CLR本质上没有意识到”这一术语包括在内.这就是我要问的问题.我怎么知道某件事是否属于我必须处理的范畴?我们一直在代码中定义要使用的东西.我们何时越过这条线并成为我需要处置的对象()?顺便说一句,我注意到那篇文章的作者从未标出答案.我不知道这是否意味着他不觉得这个问题得到了回答,或者他的跟进是否很差,但我希望我能够提炼出一些我希望了解的内容.仔细查看答案时,他们并没有真正解决哪些对象需要开发人员处理它们的问题,或者我如何知道如何识别哪些对象.我只是不知道我创建的对象或事物需要我负责处理.我认为GC和其他条款发挥作用,但同样,这就是方法.显而易见的是,大多数经验丰富的专业开发人员都知道他们创建的东西何时需要被处理掉.我不明白怎么知道. Proper use of the IDisposable interface:显然是一个受欢迎的答案(1681赞成),但明确的答案始于
好的,但我的问题是如何通过查看它是非托管资源的东西来了解?我不明白以下注释如何适用于需要处理的内容.
我不明白如何使用这种类型的解释来分类我需要处理的东西()和我不需要的东西. .net框架中有各种各样的东西;如何分离出需要我处理它们的东西?我该怎么看我告诉我我对此负责? 在那之后,答案继续谈论如何处置(),但我仍然停留在需要处理的东西上.为了让这个话题进一步复杂化,该作者后来说:“现在我们将…
所以现在我需要考虑处理一组使用内存的全新对象,我不知道它们是什么.该答案的作者后来说
我理解作者是在暗示其他文章,但作者的建议是理解“为什么”使得“如何”显而易见并不合法,因为对一个人来说显而易见的事情对另一个人来说并不总是显而易见的.甚至在那时,作者更多地关注为什么以及如何,并且我的问题是什么时候,意味着什么需要被处理(),而不是当我完成它时.我知道当我做完事情时,我只是不知道当我完成它们时我要负责哪些事情. 大多数开发人员可能明显或本能地需要处理(),但这对我来说并不明显,我确信在我的经验阶段有很多其他人,我希望能够就什么做更有针对性的对话.当然为什么有用,但在这种情况下,只有当为什么附加到什么时.例如:你必须处理一个DbContext,因为CLR不会处理它 – 因为解释了原因,它是必须处理的DbContext. 我希望有一个必须处理的一般原则,而不是一长串特定项目,对于像我这样寻求简单指导的人来说,这些项目并不是特别有用. 再一次,我认为记忆释放很重要,而且很多经验和专业知识都用于学习为什么和如何,但我仍然在努力去理解需要处理什么.一旦我理解了我必须处理的东西(),那么我就可以开始学习如何去做了. 那么这仍然是一个糟糕的问题吗?我将稍后编辑所有这些解释,以使我们能够更加专注于我所要求的内容,使帖子更简洁. 最终编辑:虽然我上面说过,我会编辑出我原本认为在问题中不必要的文字,我认为最好留下它.我认为问题的方式有可能帮助我们理解答案.即使答案永远不会改变,如果我们没有将答案与我们在脑海中解决问题的方式联系起来,我们可能也不会真正理解答案.因此,如果这个问题的框架方式与某人有关,我建议您完全阅读标记为答案的帖子以及评论.虽然最后的答案非常简单,但是有很多历史和背景对于理解这个问题的答案很重要.为了清楚起见,答案也在有关dispose()的讨论的生命周期中来回编辑.请享用… 解决方法
你不明白处置的目的.它不是用于释放与变量相关的内存.
当您确定已完成IDisposable时,请处置任何实现IDisposable的内容.
这条线为你划定了界限.当一个对象实现IDisposable时,它应该被处理掉. 我注意到变量不是根本不存在的东西.对象被丢弃.对象不是变量,变量不是对象.变量是值的存储位置.
一个原则:当物体是一次性的时候处理.
处理所有可丢弃的物品.
在使用语言时要小心.您将范围和生命周期混淆,并且您将变量与变量的内容混淆. 第一:变量的范围是程序文本的区域,其中该变量可以通过名称引用.变量的生命周期是程序执行期间的一段时间,其中变量被认为是垃圾收集器的根.范围纯粹是一个编译时的概念,生命周期纯粹是一个运行时的概念. 范围和生命周期之间的联系是局部变量的生命周期通常在控制进入变量范围时开始,并在它离开时结束.但是,各种各样的东西可以改变本地的生命周期,包括在迭代器块中或在异步方法中被关闭.抖动优化器还可以缩短或延长本地的寿命. 还要记住变量是存储,它可能指的是存储.当本地的生命周期结束时,可以回收与本地相关联的存储.但是无法保证与当地所指的东西相关的存储将在当时或之前被回收.
当对象实现IDisposable时,必须进行Dispose. (有少量的一次性物品不需要处理.例如,任务.但作为一般规则,如果是一次性的,请将其丢弃.)
完成后只处理一件事.不是之前,也不是之后.
在实现IDisposable时处理对象,并且您已完成使用它们.
当它实现IDisposable时.
一次性的.
他们检查物体是否是一次性的.如果是,他们会处置它.
它实现了IDisposable.
检查它是否是IDisposable.
任何实现IDisposable的东西都需要处理掉.
实现IDisposable的东西.
简单的指导原则是你应该丢弃一次性用品.
通过调用Dispose()来处理实现IDisposable的东西.
这是一个非常重复的问题.
感谢你在幽默中采取这个有点愚蠢的答案!
这些都是非常常见的混淆,而且大多数时候,它几乎没有什么区别.但我发现,那些正在努力理解一个概念的人通常并不是模糊和不精确.
绝大多数时候,是的. 有一些不起眼的角落案件.正如我已经提到的,TPL团队所获得的智慧是,处理Task对象不仅是不必要的,而且可能适得其反. 还有一些类型实现了IDisposable,但使用“显式接口实现”技巧使“Dispose”方法只能通过强制转换为IDisposable来访问.在大多数情况下,对象本身存在Dispose的同义词,通常称为“关闭”或某些此类事物.我不太喜欢这种模式,但有些人使用它. 对于这些对象,使用块仍然有效.如果由于某种原因你想要显式地处理这些对象而不使用则那么(1)调用“Close”方法,或者调用它,或者(2)转换为IDisposable并处理它. 一般的智慧是:如果物体是一次性的,那么处理它并不会有害,当你完成它时这是一个很好的做法. 原因是:一次性物品通常代表稀缺的共享资源.例如,某个文件可能会以某种模式打开,该模式在您打开文件时拒绝其他进程访问该文件的权限.这是礼貌的事情,以确保文件一旦完成就关闭.如果一个进程想要使用一个文件,那么很快就会有另一个进程. 或者一次性可能代表图形对象.如果一个进程中有超过一万个活动,操作系统将停止发出新的图形对象,所以当你完成它们时你必须让它们离开.
好问题.您应该在两种情况下实现IDisposable. (1)常见场景:您正在编写一个长时间保留在另一个IDisposable对象上的对象,并且“inner”对象的生命周期与“外部”对象的生命周期相同. 例如:您正在实现一个记录器类,该类打开日志文件并在日志关闭之前保持打开状态.现在你有一个固定一次性的类,所以它本身也应该是一次性的. 我注意到在这种情况下不需要“外部”对象可以最终确定.只是一次性的如果由于某种原因从未在外部对象上调用dispose,则内部对象的终结器将负责完成. (2)罕见的情况:您正在实现一个新类,该类向操作系统或其他外部实体询问必须积极清理的资源,并且该资源的生命周期与持有它的对象的生命周期相同. 在这种非常罕见的情况下,您首先应该问自己是否有任何方法可以避免它.对于初学者到中级程序员来说,这是一个糟糕的情况.您真的需要了解CLR如何与非托管代码交互以使这些东西变得扎实. 如果你无法避免它,你不应该尝试自己实现处理和终结逻辑,特别是如果非托管对象由Windows句柄表示.应该已经有大多数句柄代表的OS服务包装,但如果没有,你想要做的是仔细研究IntPtr,SafeHandle和HandleRef之间的关系. IntPtr,SafeHandle and HandleRef – Explained 如果您确实需要为非托管,非基于句柄的资源编写处理逻辑,并且资源需要通过最终确定来支持处理,那么您将面临重大的工程挑战. 标准的配置模式代码可能看起来很简单但是在编写正确的终结逻辑时存在真正的微妙之处,这些逻辑在错误条件下是健壮的.请记住,终结器在不同的线程上运行,并且可以在线程中止场景中与构造函数并发运行在该线程上.编写线程安全逻辑,当一个对象仍然在另一个线程上构建时清理它可能非常困难,我建议不要尝试. 有关编写终结器的挑战的更多信息,请参阅我关于该主题的系列文章:http://ericlippert.com/2015/05/18/when-everything-you-know-is-wrong-part-one/ 你没问的问题,但我会回答:
是.许多人在希望拥有具有以下语义的编码模式时实现IDisposable: >改变世界 因此,例如,“冒充管理员,执行一些管理任务,恢复普通用户”.或者“开始处理事件,在事件发生时执行操作,停止处理事件”.或者“创建一个内存中的错误跟踪器,做一些可能会出错的东西,停止跟踪错误”.等等.你得到了一般模式. 这对于一次性模式来说是不合适的,但这并不能阻止人们编写代表任何非托管资源的类,但仍然像他们那样实现IDisposable. 这种观点使我成为少数;滥用这种机制,很多人都没有任何问题.但是,当我看到一个一次性的时候,我觉得“这个班级的作者希望我在我做好和准备好之后能够礼貌地清理自己.”但是这个类的实际合同通常是“你必须在程序中的某个特定位置处理它,如果你不这样做,那么程序逻辑的其余部分将是错误的,直到你做”.这不是我期望在看到一次性用品时必须实施的合同.我希望我必须尽心尽力地在方便时清理资源. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |