我正在尝试学习如何在C#中有效地使用委托,我只是想知道是否有人可以指导我...以下是使用委托的示例实现...我所做的只是传递一个值通过从一个班级到另一个班级的代表...请告诉我这是否是正确的实施方式......还有你的建议......
此外,请注意我已取消注册代表:
void FrmSample_FormClosing(object sender, FormClosingEventArgs e)
{
sampleObj.AssignValue -= new Sample.AssignValueDelegate(AssignValue);
}
这是否需要取消注册?
以下是我写的代码..
public partial class FrmSample : Form
{
Sample sampleObj;
public FrmSample()
{
InitializeComponent();
this.Load += new EventHandler(FrmSample_Load);
this.FormClosing += new FormClosingEventHandler(FrmSample_FormClosing);
sampleObj = new Sample();
sampleObj.AssignValue = new Sample.AssignValueDelegate(AssignValue);
}
void FrmSample_FormClosing(object sender, FormClosingEventArgs e)
{
sampleObj.AssignValue -= new Sample.AssignValueDelegate(AssignValue);
}
void FrmSample_Load(object sender, EventArgs e)
{
sampleObj.LoadValue();
}
void AssignValue(string value)
{
MessageBox.Show(value);
}
}
class Sample
{
public delegate void AssignValueDelegate(string value);
public AssignValueDelegate AssignValue;
internal void LoadValue()
{
if (AssignValue != null)
{
AssignValue("This is a test message");
}
}
}
请提供您对这是否正确的反馈......
谢谢, 拉姆
答案 0 :(得分:6)
仅当事件引用使包含委托目标的对象保持活动太长时,才需要显式取消注册事件处理程序。在您的情况下,sampleObj将具有对Form对象的引用。 C#语法糖隐藏了这一点,编译器实际上生成了这段代码:
sampleObj.AssignValue = new Sample.AssignValueDelegate(的此下, AssignValue);
如果此参数初始化Delegate.Target属性, AssignValue 参数初始化Delegate.Method属性。
这意味着只要sampleObj对象保持引用,表单对象也会保持引用,并且不会被垃圾回收。但是,在您的情况下,唯一具有sampleObj引用的对象是表单对象本身。垃圾回收器没有像这样的循环引用的麻烦,并且会检测到没有对这两个对象的其他引用。并将同时收集它们。
有一个(不常见的)例外,你将遇到问题,sampleObj类在表单关闭后生成事件。如果事件由表单之外的某些事件触发,例如某些硬件事件,则可能发生这种情况。该事件仍然可以在表单类中运行代码。您通常会很快注意到这一点,任何在表单中引用控件的尝试都会抛出ObjectDisposed异常。
答案 1 :(得分:1)
没有必要取消注册代表。您将示例obj存放在表单范围内,并在表单关闭后销毁
答案 2 :(得分:1)
在这种情况下,Action委托可能更合适 - 它是一种特定形式的委托,需要1-3个参数且没有返回值: