我想问一下清洁的效率和处理列表中的对象的效率是什么?
?是通过调用list.clear()方法将自动清洁其收集的所有对象?
例如,请考虑以下示例
public partial class Form1 : Form
{
FontCollection m_fontCollection;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
m_fontCollection = new FontCollection();
for (int i = 0; i < 5000; i++)
{
Font font = new Font("Arial", 23);
FontImpl impl = new FontImpl(font, Color.Black);
impl.AfterChange +=
new FontImpl.AfterChangeHandler(impl_AfterChange);
m_fontCollection.Add(impl);
}
m_fontCollection.Dispose();
MessageBox.Show("TakeSnap");
}
void impl_AfterChange()
{
throw new NotImplementedException();
}
}
public class FontCollection : IEnumerable, IDisposable
{
IList<FontImpl> m_Implementation = new List<FontImpl>();
internal void Add(FontImpl impl)
{
this.m_Implementation.Add(impl);
}
public IEnumerator GetEnumerator()
{
return this.m_Implementation.GetEnumerator();
}
public void Dispose()
{
m_Implementation.Clear();
m_Implementation = null;
}
}
public class FontImpl
{
private Font m_Font;
private Color m_color;
public FontImpl(Font newFont, Color newColcor)
{
m_Font = newFont;
m_color = newColcor;
}
public event AfterChangeHandler AfterChange;
public delegate void AfterChangeHandler();
}
当我运行上述应用程序蚂蚁内存profiler时,我可以看到内存泄漏字体和fontfamily(我无法上传屏幕)以及如何删除这些泄漏
通常,您不需要担心垃圾收集,以及何时发生垃圾。当对其参考为零时,一个对象有资格使用GC。
您应该注意的是IDisposable
对象。使用IDisposable
对象完成后,您确实需要在其上调用Dispose()
。如果对象生活在函数函数的本地范围内,则using
块使它变得容易:
using (var resource = new SomeIDisposable()) {
// use resource
// resource.Dispose() is automatically called, *even if* an exception
// is thrown.
}
you can 通过以"悬空引用"对象导致内存泄漏,这阻止了它们被收集到垃圾。最常见的原因是事件处理程序。当您订阅对象A
暴露的事件时,在对象B
上使用事件处理程序,A
将引用B
:
class B {
void hook_up_to(A a) {
a.SomeEvent += Handler; // `a` gets a reference to `this`
}
void Handler(object sender, EventArgs e) {
}
}
class Program {
private A _a = new A();
static void SomeMethod() {
var b = new B();
b.hook_up_to(_a); // _a now has a reference to b
// b goes out of scope.
}
}
通常,当b
脱离范围时,它引用的对象将符合垃圾收集的条件。但是,在这种情况下,b
连接到成员变量_a
发布的事件,这导致_a
获得了对b
的参考。现在,有一个对b
的出色引用,这是不可能的 1 可以清除的,而b
不合格GC。这是一个内存泄漏。
1 在这种情况下,唯一的参考b
的方法是this
指针,如果/触发事件处理程序时。
您无需在课堂上实现IDisposable
。通常,您的课程唯一需要实现IDisposable
的时间是需要处理其他类时(数据库和网络连接之类的东西,以及不受管理的对象)。
在您的示例中,您可能需要考虑在button1_Click
中制作m_fontCollection
A local 变量,因为您正在完全在该方法中创建和处置它。如果您将其定为本地,则一旦button1_Click
退出.../div>
clear只需从列表中删除所有内容即可。在您的情况下,您有一个可iDisposable对象的列表,需要在列表中的所有项目上调用Distose。呼叫Clear不会做到这一点。
您的fontimpl应该实现Idisposable,因为它可以管理一个可iDisposable的对象:
public void Dispose() {
if (m_Font != null) {
m_Font.Dispose();
m_Font = null;
}
}
,您的fontcollection处置应该像这样:
public void Dispose()
{
foreach(FontImpl font in m_Implementation) {
font.Dispose();
}
m_Implementation.Clear();
m_Implementation = null;
}
在您显示的代码的情况下,您具有实现IDisposable
的Font
对象,因此应处置。这些对象由您的FontImpl
类管理,因此FontImpl
应实现IDisposable
。您的FontCollection
类包含一个FontImpl
对象的列表,该对象现在应该是可置的,因此FontCollection
需要实现IDisposable
。
您应该阅读有关Idisposable模式的阅读(因此,此答案提供了一些很棒的信息-https://stackoverflow.com/a/538238/416574)。
话虽如此,从您提供的代码片段中,您似乎没有从FontCollection
获得任何东西以包装列表。除非您还将与该类别做其他事情,否则我只会有一个列表作为成员变量。这样,在您表格的Dispose
方法中,您可以步行列表并处理FontImpl
对象。如果您想保护双重处理,请在处置所有内容后清空清单。