首先,发布帖子,以便我简短回答。
我在标签页中添加了一个控件。由于仅具有一个变量的限制,但是名称属性不同。我决定将我创建的所有文本框对象添加到列表中。文本框是通过循环创建的。
现在,当我删除它们时,我知道我必须调用dispose方法。我必须删除控件,最后减少事件处理程序。
我的问题是这些实际上是做什么的。我希望删除后的文本框列表不再存在。因此,如果我调用其属性(例如名称等),则该列表应为空或抛出异常。
那么为什么这些文本框仍在我的列表中并且仍然起作用?好像我从未删除过它们。尽管它们不再存在于我的表单中,但看起来它们仍然生活在后台,这可能意味着内存泄漏或程序变慢。对于这些方法的作用以及为何文本框对象仍然存在的任何解释,我将不胜感激。
最后一点,我来自cpp。因此,我看到它曾经被动态创建的对象称为Delete的方式,该变量将不再起作用。
此外,如果需要,我可以添加我的代码。
编辑:我的代码如下
用于添加到标签页:
if (int.TryParse((sender as TextBox).Text, out int Stories))
{
Console.WriteLine(Stories); this.Stories = Stories;
string L_name = "Label_";
string T_name = "TextBox_";
int counter = 1;
int yIncr = Story_label.Size.Height + 3;//widthoftextbox+spacing
List<string> L_name_arr = new List<string>
{
L_name + counter.ToString()
};
List<string> T_name_arr = new List<string>
{
T_name + counter.ToString()
};
for (int i = 0; i < Stories; i++)
{
//create new labels and textboxes below
//have a max value.
Label L_ = new Label();
Model_Geometry_tab.Controls.Add(L_);
L_.Location = new System.Drawing.Point(Story_label.Location.X, Story_label.Location.Y + yIncr * counter);//increasing increment every iteration
L_.Name = L_name_arr[i];
L_.Size = new System.Drawing.Size(Story_label.Size.Width, Story_label.Size.Height);
L_.Text = "Story" + counter.ToString();
TextBox T_ = new System.Windows.Forms.TextBox();
//T_.BackColor = System.Drawing.SystemColors.ActiveBorder;
T_.Location = new System.Drawing.Point(Story_input.Location.X, Story_input.Location.Y + yIncr * counter);
T_.MaxLength = 1000;
T_.Name = T_name_arr[i];
T_.Size = new System.Drawing.Size(Story_input.Size.Width, Story_input.Size.Height);
T_.KeyDown += new System.Windows.Forms.KeyEventHandler(TextBox_1_KeyDown);
T_.MouseClick += new System.Windows.Forms.MouseEventHandler(textBox_other_MouseClick);
T_.MouseHover += new System.EventHandler(textBox2_MouseHover);
Story_arr.Add(T_);
Model_Geometry_tab.Controls.Add(T_);
//incr counter
counter++;
//addnewlabeltags
L_name_arr.Add(L_name + counter.ToString());
//addnewtexttags
T_name_arr.Add(T_name + counter.ToString());
}
}
else
{
MessageBox.Show("Enter an integer value please!");
}
要删除它们,我使用了Story_arr列表;
private void button2_Click(object sender, EventArgs e)
{
if (Story_arr.Count != 0 && !a)
{
foreach (var item in Story_arr)
{
Console.WriteLine(item.Name);
item.KeyDown -= new System.Windows.Forms.KeyEventHandler(TextBox_1_KeyDown);
item.MouseClick -= new System.Windows.Forms.MouseEventHandler(textBox_other_MouseClick);
item.MouseHover -= new System.EventHandler(textBox2_MouseHover);
Model_Geometry_tab.Controls.Remove(item);
item.Dispose();
}
a = true;
}
else if (a)
{
foreach (var item in Story_arr)
{
Console.WriteLine(item.IsDisposed);
}
}
else
MessageBox.Show("It is empty list");
}
答案 0 :(得分:1)
当您调用IDisposable.Dispose
时,并不表示该对象已删除。处置对象旨在清除任何内部或外部资源。在WinForms中,这特别意味着要清理所有基础窗口句柄等。
在.NET受管内存中,只有垃圾收集器最终将删除对象。在您的特定情况下,尽管GC永远不会收集您已删除的控件,因为您仍将其保留在列表中。将它们包含在列表中意味着该对象仍被引用,即它们尚未失效。 GC将仅收集死物。
只需手动从列表中删除控件,您就可以了。您还可以监听控件的Disposed
事件,并将其从事件处理程序的列表中删除。这样会自动处理从列表中删除所有已处置控件的问题。
更高级的解决方案是不将控件直接添加到列表中,而是添加弱引用。 WeakReference
允许您访问对象,但不会阻止垃圾回收。但是,我个人更希望手动取消引用该对象,因为这更直接,而且更不易出错。