如何在.net 中处理一个类? [英] How to dispose a class in .net?

查看:20
本文介绍了如何在.net 中处理一个类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

.NET 垃圾收集器最终会释放内存,但如果您想立即收回​​内存怎么办?需要在类MyClass中使用什么代码来调用

The .NET garbage collector will eventually free up memory, but what if you want that memory back immediately? What code do you need to use in a class MyClass to call

MyClass.Dispose()

并释放MyClass中变量和对象使用的所有空间?

and free up all the used space by variables and objects in MyClass?

推荐答案

IDisposable 与释放内存无关.IDisposable 是一种释放非托管资源的模式——而内存绝对是一种托管资源.

IDisposable has nothing to do with freeing memory. IDisposable is a pattern for freeing unmanaged resources -- and memory is quite definitely a managed resource.

指向 GC.Collect() 的链接是正确答案,尽管 Microsoft .NET 文档通常不鼓励使用此函数.

The links pointing to GC.Collect() are the correct answer, though use of this function is generally discouraged by the Microsoft .NET documentation.

为这个答案赚了很多钱,我觉得有责任详细说明它,以免 .NET 资源管理的新手得到错误的印象.

Having earned a substantial amount of karma for this answer, I feel a certain responsibility to elaborate on it, lest a newcomer to .NET resource management get the wrong impression.

在 .NET 进程中,有两种资源——托管和非托管.托管"意味着运行时控​​制资源,而非托管"意味着它是程序员的责任.今天在 .NET 中,我们真正关心的只有一种托管资源——内存.程序员告诉运行时分配内存,然后由运行时确定何时可以释放内存..NET 用于此目的的机制称为垃圾收集,您可以找到很多只需使用 Google 即可在互联网上获取有关 GC 的信息.

Inside a .NET process, there are two kinds of resource -- managed and unmanaged. "Managed" means that the runtime is in control of the resource, while "unmanaged" means that it's the programmer's responsibility. And there really is only one kind of managed resource that we care about in .NET today -- memory. The programmer tells the runtime to allocate memory and after that it's up to the runtime to figure out when the memory can freed. The mechanism that .NET uses for this purpose is called garbage collection and you can find plenty of information about GC on the internet simply by using Google.

对于其他类型的资源,.NET 对清理它们一无所知,因此它必须依靠程序员来做正确的事情.为此,平台给了程序员三个工具:

For the other kinds of resources, .NET doesn't know anything about cleaning them up so it has to rely on the programmer to do the right thing. To this end, the platform gives the programmer three tools:

  1. VB 和 C# 中的 IDisposable 接口和using"语句
  2. 终结者
  3. 由许多 BCL 类实现的 IDisposable 模式

第一个允许程序员有效地获取资源,使用它,然后在同一方法中释放它.

The first of these allows the programmer to efficiently acquire a resource, use it and then release it all within the same method.

using (DisposableObject tmp = DisposableObject.AcquireResource()) {
    // Do something with tmp
}
// At this point, tmp.Dispose() will automatically have been called
// BUT, tmp may still a perfectly valid object that still takes up memory

如果AcquireResource"是一个工厂方法(例如)打开一个文件并且Dispose"自动关闭文件,那么这个代码不会泄漏文件资源.但是tmp"对象本身的内存很可能仍然被分配.那是因为 IDisposable 接口完全没有与垃圾收集器的连接.如果您确实想确保内存被释放,您唯一的选择是调用 GC.Collect() 以强制进行垃圾回收.

If "AcquireResource" is a factory method that (for instance) opens a file and "Dispose" automatically closes the file, then this code cannot leak a file resource. But the memory for the "tmp" object itself may well still be allocated. That's because the IDisposable interface has absolutely no connection to the garbage collector. If you did want to ensure that the memory was freed, your only option would be to call GC.Collect() to force a garbage collection.

然而,无论如何强调这可能不是一个好主意.通常让垃圾收集器做它应该做的事情要好得多,即管理内存.

However, it cannot be stressed enough that this is probably not a good idea. It's generally much better to let the garbage collector do what it was designed to do, which is to manage memory.

如果资源使用时间较长,以至于其生命周期跨越多种方法,会发生什么情况?显然,using"语句不再适用,因此程序员在使用完资源后必须手动调用Dispose".如果程序员忘记了会发生什么?如果没有回退,那么进程或计算机最终可能会耗尽未正确释放的资源.

What happens if the resource is being used for a longer period of time, such that its lifespan crosses several methods? Clearly, the "using" statement is no longer applicable, so the programmer would have to manually call "Dispose" when he or she is done with the resource. And what happens if the programmer forgets? If there's no fallback, then the process or computer may eventually run out of whichever resource isn't being properly freed.

这就是终结器的用武之地.终结器是您的类中的一种方法,它与垃圾收集器有着特殊的关系.GC 承诺——在为该类型的任何对象释放内存之前——它会首先让终结器有机会进行某种清理.

That's where finalizers come in. A finalizer is a method on your class that has a special relationship with the garbage collector. The GC promises that -- before freeing the memory for any object of that type -- it will first give the finalizer a chance to do some kind of cleanup.

所以在文件的情况下,理论上我们根本不需要手动关闭文件.我们可以等到垃圾收集器找到它,然后让终结器完成工作.不幸的是,这在实践中效果不佳,因为垃圾收集器的运行是不确定的.文件保持打开状态的时间可能比程序员预期的要长得多.如果打开的文件足够多,系统在尝试打开其他文件时可能会失败.

So in the case of a file, we theoretically don't need to close the file manually at all. We can just wait until the garbage collector gets to it and then let the finalizer do the work. Unfortunately, this doesn't work well in practice because the garbage collector runs non-deterministically. The file may stay open considerably longer than the programmer expects. And if enough files are kept open, the system may fail when trying to open an additional file.

对于大多数资源,我们需要这两样东西.我们希望约定能够说我们现在已经完成了这个资源",并且我们希望确保如果我们忘记手动进行清理,至少有一些机会自动进行清理.这就是IDisposable"模式发挥作用的地方.这是一个约定,允许 IDispose 和终结器很好地协同工作.您可以通过查看 IDisposable 的官方文档.

For most resources, we want both of these things. We want a convention to be able to say "we're done with this resource now" and we want to make sure that there's at least some chance for the cleanup to happen automatically if we forget to do it manually. That's where the "IDisposable" pattern comes into play. This is a convention that allows IDispose and a finalizer to play nicely together. You can see how the pattern works by looking at the official documentation for IDisposable.

底线:如果您真正想做的只是确保释放内存,那么 IDisposable 和终结器将无济于事.但是 IDisposable 接口是所有 .NET 程序员都应该理解的极其重要的模式的一部分.

Bottom line: If what you really want to do is to just make sure that memory is freed, then IDisposable and finalizers will not help you. But the IDisposable interface is part of an extremely important pattern that all .NET programmers should understand.

这篇关于如何在.net 中处理一个类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆