gpt4 book ai didi

c# - 列表对象的垃圾收集

转载 作者:行者123 更新时间:2023-11-30 22:22:09 29 4
gpt4 key购买 nike

请问在List(Of Object)中收集到的对象的clean和dispose效率如何?

是不是调用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();
}

当我运行上面的应用程序 ANTS 内存分析器时,我可以看到内存泄漏 Font 和 FontFamily(我无法上传屏幕)以及如何消除这些泄漏

最佳答案

一般来说,您不必担心垃圾回收,也不需要担心垃圾回收何时发生。当对对象的引用为零时,该对象符合 GC 条件。

然而,您应该注意的是 IDisposable对象。当您完成 IDisposable 对象时,您确实需要对其调用 Dispose()。如果对象存在于函数的局部范围内,那么 using block 可以使这变得简单:

using (var resource = new SomeIDisposable()) {
// use resource

// resource.Dispose() is automatically called, *even if* an exception
// is thrown.
}

可以通过以对象的“悬空引用”结尾来导致内存泄漏,这会阻止它们被垃圾收集。最常见的原因是事件处理程序。当您订阅对象 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 指针。

关于c# - 列表对象的垃圾收集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13984805/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com