Jas*_*n94 3 c# events delegates
我在我的类上定义了一个事件,我想让该类的一个方法成为事件的处理程序.
这是我到目前为止:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DelegatesAndEvents
{
class Program
{
static void Main(string[] args)
{
Person p = new Person();
p.NameChangeEventHandler += new Person.NameChangeEventHandlerDel;
p.Name = "Paul";
}
}
class Person
{
#region Events
public delegate void NameChangeEventHandlerDel(object sender, EventArgs args);
public event EventHandler NameChangeEventHandler;
protected void NameChange(EventArgs arg)
{
Console.WriteLine("Name change...");
}
#endregion
#region Properties
private string name;
public string Name
{
get { return name; }
set
{
NameChange(null);
name = value;
}
}
#endregion
public Person(string name = "John")
{
this.name = name;
}
}
}
Run Code Online (Sandbox Code Playgroud)
如何注册事件处理程序而不必在Main中执行?
阅读如何:发布符合.NET Framework准则的事件,以获取有关如何创建和使用事件的更多信息.那里的例子不太清楚,所以我将在这里介绍这个过程.
定义事件所需的第一部分是要使用的事件处理程序委托.这是所有希望收到有关此活动的通知的人所需的方法签名.您通常不必自己创建新的委托,您应该使用现有EventHandler(或通用EventHandler<TEventArgs>)委托.如果您不需要包含有关该事件的任何其他参数,则可以使用非泛型版本.否则你将使用通用版本.在您的情况下,没有任何关于该事件的其他参数,因此您应该使用非泛型EventHandler.
(如果您希望能够将旧值和新值等信息作为参数包含在内,那么您将使用通用版本和派生自的相应类EventArgs.这是一个高级主题,因此我们将跳过它.)
下一部分是定义事件.就像你为你的班级定义一个属性一样简单.这里的区别在于您使用event关键字来指定您要定义的事件后跟要使用的委托和事件的名称.命名事件以更改属性的约定通常在模式中PropertyNameChanged.由于您需要在Name属性更改时触发的事件,因此您应该将其命名为:NameChanged.
public event EventHandler NameChanged;
Run Code Online (Sandbox Code Playgroud)
可选(但强烈推荐)的步骤是定义用于引发事件的方法.这将使您更容易在需要时举起活动.通常的命名约定类似于事件的命名方式.这一次,.所以你在这里命名.它通常被定义为受保护的虚方法,派生类可以轻松地覆盖它.函数的参数应该是事件所需的参数.由于此处没有参数,因此签名中可能没有参数.OnEventNameOnNameChanged
有了这一切,只需要调用事件处理程序.它只是一个代表,所以只需要它.但是不要忘记检查它是否是null第一个,这表示没有注册事件处理程序.处理程序的参数应该是this(引发事件的对象)和参数应该是什么.在这种情况下,没有参数,但你应该返回一个"空"的实例EventArgs.
protected virtual void OnNameChanged()
{
EventHandler nameChanged = NameChanged; // always a good idea to store in a local variable
if (nameChanged != null)
{
nameChanged(this, new EventArgs());
}
}
Run Code Online (Sandbox Code Playgroud)
最后一部分是在你的属性中连接它.如果赋值将更改属性的值,则您希望引发事件.非常简单,只需检查旧值是否与新值不同.如果是,请更改它并引发事件.否则,别做什么.
private string name;
public string Name
{
get { return name; }
set
{
if (!String.Equals(value, name)) // if the value gets changed...
{
name = value;
OnNameChanged(); // raise the event!!!
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在我们已经完成了事件的设置,您希望能够为此事件注册一些处理程序.为了能够做到这一点,首先我们需要Person我们想要等待Name更改的实例,并且我们需要一个具有正确的事件签名的事件处理方法.该事件被定义为使用EventHandler委托,因此我们需要一个带签名的方法:void NameChanged(object sender, EventArgs e).请记住,sender参数是引发事件的对象.在这种情况下,它是一个Person对象,因此我们可以获取已更改的对象,并在需要时检查属性.你可以随意命名.我亲自去的模式是:.所以在这种情况下,我给它命名:.InstanceName_EventNameperson_NameChanged
static void person_NameChanged(object sender, EventArgs e)
{
Person person = (Person)sender; // cast back to a Person so we can see what's changed
Console.WriteLine("The name changed!");
Console.WriteLine("It is now: " + person.Name); // let's print the name
}
Run Code Online (Sandbox Code Playgroud)
定义完成后,将处理程序添加到事件中,如果有任何更改,我们会收到通知.
person.NameChanged += person_NameChanged;
Run Code Online (Sandbox Code Playgroud)
如果您希望处理程序完全在类中,您可以在类中注册该事件.无需外接电线.你可以从构造函数中完成它.我不建议将您的代码添加到OnNameChanged()事件提升方法中,该方法应该保留用于简单地引发事件.
public Person(string name = "John")
{
this.name = name;
this.NameChanged += builtin_NameChanged;
}
private static void builtin_NameChanged(object sender, EventArgs e)
{
Person person = (Person)sender; // cast back to a Person so we can see what's changed
Console.WriteLine("The name changed!");
Console.WriteLine("It is now: " + person.Name); // let's print the name
}
Run Code Online (Sandbox Code Playgroud)
请注意,在此特定示例中,处理程序是静态的,因此它不依赖于单个实例.它适用于任何Person一般情况.请注意,由于它是静态的,因此您无法this在方法中使用,这就是为什么需要使用发送方进行转换.它是否是静态的取决于你最终,无论哪种方式都应该没问题.
所以把这一切放在一起,这就是你能做到的:
class Person
{
public Person(string name = "John")
{
this.name = name;
this.NameChanged += builtin_NameChanged;
}
public string Name
{
get { return name; }
set
{
if (!String.Equals(value, name))
{
name = value;
OnNameChanged();
}
}
}
public event EventHandler NameChanged;
protected virtual void OnNameChanged()
{
EventHandler nameChanged = NameChanged;
if (nameChanged != null)
{
nameChanged(this, new EventArgs());
}
}
private static void builtin_NameChanged(object sender, EventArgs e)
{
Person person = (Person)sender;
Console.WriteLine("The name changed!");
Console.WriteLine("It is now: " + person.Name);
}
private string name;
}
class Program
{
static void Main(string[] args)
{
Person person = new Person();
person.Name = "Paul";
}
}
Run Code Online (Sandbox Code Playgroud)