.NET 构造函数和内存管理问题
来自 C++ 等更底层的语言,并看到 .NET 内存管理的透明性,我对我编写的一段代码进行了一场音乐会。
在 C++ 中,每个对象(规定的设计实践和内存管理的特殊性)都必然需要有一个构造函数和一个析构函数。在 .NET 中,并不经常需要析构函数,并且何时需要析构函数以及如何使用它们有不同的模式。我的问题是这样的。如果我有以下类似的代码(在 VB.NET 中,但同样适用于 C#),
Dim myObj As New MyClass( <some parameters here> )
后面的代码后面跟着以下行,
myObj = New MyClass( <some other parameters> )
上面的代码会导致内存泄漏吗?面对这种情况,正确的思考方式是什么?
Coming from more low-level languages like C++, and seeing how transparent .NET memory management is, I've got a concert about a piece a line of code I've written.
In C++, every object necessarily (dictated design practices and peculiarities of memory management) needs to have a constructor and a destructor. In .NET, destructors aren't needed as often, and there are different patterns of when they are required and how to use them. My question is this. If I have the following like of code (in VB.NET, but equally applies to C#)
Dim myObj As New MyClass( <some parameters here> )
followed by the following line later in code
myObj = New MyClass( <some other parameters> )
will the above cause a memory leak? What is the correct way of thinking about such situations?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
不,这不会导致内存泄漏。你写的代码没问题。关于 C#(以及其他 .NET 语言),您必须记住的一点是它们是垃圾收集的。
与 C++ 不同,在 C++ 中,您明确负责自己创建和释放内存,但在 .NET 的托管世界中情况并非如此。您所需要担心的只是创建对象。当不再有任何剩余的引用时,它就符合垃圾回收的条件。说真的,我知道这听起来很奇怪,考虑到你的其他语言背景,但你真的应该让垃圾收集器担心这些事情。 “正确的思考这种情况的方法”确实是根本不去想它们!
事实上,唯一需要编写析构函数(从而担心内存管理)的情况是您的类使用非托管对象(例如窗口句柄、GDI+ 对象等)或其他需要显式关闭的对象(文件句柄、数据库连接等)。在 .NET 世界中,您希望尽可能少地编写析构函数,因为这样做会稍微降低性能。具体细节在于垃圾收集算法的实现,以及在什么时候可以收集对象,但您不应该尝试学习所有这些。
要记住的重要一点是,如果您确实需要在对象被销毁时“清理”,则应该实现
IDisposable
接口,像许多 WinForms 类一样(例如Control
)执行此操作在内部使用非托管对象。以下是一些很好的资源,可用于详细了解 .NET 的垃圾收集模型:
No, that will not cause a memory leak. The code you wrote is just fine. The thing you have to remember about C# (and the other .NET languages) is that they are garbage collected.
Unlike C++, where you are explicitly responsible for creating and freeing memory yourself, that's not the case in the managed world of .NET. All you have to worry about is creating the object. When there are no longer any remaining references to it, it becomes eligible for garbage collection. Seriously, I know this sounds weird, given your background in other languages, but you really should just let the garbage collector worry about such things. The "correct way of thinking about such situations" is indeed not to think about them at all!
In fact, the only time that you need to write a destructor (and thus worry about memory management) is if your class makes use of unmanaged objects (such as window handles, GDI+ objects, etc.) or other objects that require explicit closing (file handles, database connections, etc.). In the .NET world, you want to write a destructor as rarely as possible, because there's a slight performance penalty in doing so. The specifics lie in the implementation of the garbage collection algorithm, and at what point the object can be collected, but you shouldn't try to learn all that.
The important thing to remember is that if you do need to "clean up" when the object gets destroyed, you should implement the
IDisposable
interface, like many of the WinForms classes (e.g.Control
) do that use unmanaged objects internally.Here are a couple of good resources for learning more about .NET's garbage collection model:
.NET 中的对象会被垃圾回收。您不需要删除它们。
一些持有非托管状态的对象(例如通过 P/Invoke 从 C 函数分配的对象),例如 System.IO.Stream,将实现终结器和 IDisposable。您可以通过两种方式使用它们:
或者更安全的方式:
即使您不调用 Dispose,这些对象最终也会被垃圾收集,但无法保证何时会发生,因此这样做通常是一个好主意。
您自己的任何具有一次性成员的类也应该实现 IDisposable 来清理它们。
Objects in .NET are garbage collected. You don’t need to delete them.
Some objects that hold unmanaged state (like something allocated from a C function through P/Invoke), such as System.IO.Stream, will implement a finalizer and IDisposable. You can use these in two ways:
Or the safer way:
These objects will be garbage collected eventually even if you don’t call Dispose, but there is no guarantee when that will happen so it’s usually a good idea to do so.
Any of your own classes that have disposable members should also implement IDisposable to clean them up.
否不会导致内存泄漏。 垃圾收集器将回收以前的对象。
所有托管资源使用的内存将由垃圾收集器处理。
No it will not cause memory leak. Garbage collector will reclaim the previous object.
Memory used by all managed resources will be handled by the Garbage Collector.
消极的。 CLR 使用引用计数器维护对所有实例的引用;内存垃圾收集器经常会运行并查找没有代码段引用的所有引用,然后释放该内存。
在您的情况下,这只是意味着在将来的某个时刻,由于您不再引用 MyClass 的原始实例,垃圾收集器将为您释放它的内存。这是正常操作;所以您不必担心! =D
Negative. The CLR maintains a reference to all instances with a reference counter; every so often the Memory garbage collector will run and find all references where no piece of code is referencing and it will release that memory.
In your situation, it simply means that at some point in the future, since you no longer reference the original instance of MyClass, the garbage collector will release it's memory for you. This is normal operation; so you don't have to worry about it! =D