我理解事件的目的,特别是在创建用户界面的上下文中。我认为这是创建事件的原型:
public void EventName(object sender, EventArgs e);
事件处理程序做什么,为什么需要它们,以及如何创建一个?
我理解事件的目的,特别是在创建用户界面的上下文中。我认为这是创建事件的原型:
public void EventName(object sender, EventArgs e);
事件处理程序做什么,为什么需要它们,以及如何创建一个?
当前回答
我对这些事件的理解是;
委托:
保存要执行的方法/方法的引用的变量。这使得像传递变量一样传递方法成为可能。
创建和调用事件的步骤:
事件是委托的实例 由于事件是委托的实例,因此我们必须首先定义委托。 指定在事件触发时执行的方法/方法(调用委托) 触发事件(调用委托)
例子:
using System;
namespace test{
class MyTestApp{
//The Event Handler declaration
public delegate void EventHandler();
//The Event declaration
public event EventHandler MyHandler;
//The method to call
public void Hello(){
Console.WriteLine("Hello World of events!");
}
public static void Main(){
MyTestApp TestApp = new MyTestApp();
//Assign the method to be called when the event is fired
TestApp.MyHandler = new EventHandler(TestApp.Hello);
//Firing the event
if (TestApp.MyHandler != null){
TestApp.MyHandler();
}
}
}
}
其他回答
下面是一个代码示例,可能会有所帮助:
using System;
using System.Collections.Generic;
using System.Text;
namespace Event_Example
{
// First we have to define a delegate that acts as a signature for the
// function that is ultimately called when the event is triggered.
// You will notice that the second parameter is of MyEventArgs type.
// This object will contain information about the triggered event.
public delegate void MyEventHandler(object source, MyEventArgs e);
// This is a class which describes the event to the class that receives it.
// An EventArgs class must always derive from System.EventArgs.
public class MyEventArgs : EventArgs
{
private string EventInfo;
public MyEventArgs(string Text) {
EventInfo = Text;
}
public string GetInfo() {
return EventInfo;
}
}
// This next class is the one which contains an event and triggers it
// once an action is performed. For example, lets trigger this event
// once a variable is incremented over a particular value. Notice the
// event uses the MyEventHandler delegate to create a signature
// for the called function.
public class MyClass
{
public event MyEventHandler OnMaximum;
private int i;
private int Maximum = 10;
public int MyValue
{
get { return i; }
set
{
if(value <= Maximum) {
i = value;
}
else
{
// To make sure we only trigger the event if a handler is present
// we check the event to make sure it's not null.
if(OnMaximum != null) {
OnMaximum(this, new MyEventArgs("You've entered " +
value.ToString() +
", but the maximum is " +
Maximum.ToString()));
}
}
}
}
}
class Program
{
// This is the actual method that will be assigned to the event handler
// within the above class. This is where we perform an action once the
// event has been triggered.
static void MaximumReached(object source, MyEventArgs e) {
Console.WriteLine(e.GetInfo());
}
static void Main(string[] args) {
// Now lets test the event contained in the above class.
MyClass MyObject = new MyClass();
MyObject.OnMaximum += new MyEventHandler(MaximumReached);
for(int x = 0; x <= 15; x++) {
MyObject.MyValue = x;
}
Console.ReadLine();
}
}
}
文章中有很棒的技术答案!我没有任何技术上的补充。
在语言和软件中出现新功能的主要原因之一是市场营销或公司政治!:-)这绝不能被低估!
我认为这也适用于代表和活动!我发现它们很有用,为c#语言增加了价值,但另一方面,Java语言决定不使用它们!他们认为无论你用委托解决什么问题,你都可以用语言的现有特性来解决,比如接口。
2001年左右,微软发布了。net框架和c#语言,作为Java的竞争解决方案,所以拥有Java没有的新功能是件好事。
c#有两个术语,委托和事件。让我们从第一个开始。
委托
委托是对方法的引用。就像你可以创建一个实例的引用:
MyClass instance = myFactory.GetInstance();
你可以使用委托来创建一个方法的引用:
Action myMethod = myFactory.GetInstance;
现在你有了一个方法的引用,你可以通过引用调用这个方法:
MyClass instance = myMethod();
但你为什么要这么做?你也可以直接调用myFactory.GetInstance()。在这种情况下你可以。但是,有很多情况需要考虑,您不希望应用程序的其余部分了解myFactory或直接调用myFactory. getinstance()。
一个明显的例子是,如果你想从一个中心位置(也就是工厂方法模式)将myFactory.GetInstance()替换为myOfflineFakeFactory.GetInstance()。
工厂方法模式
所以,如果你有一个TheOtherClass类,它需要使用myFactory. getinstance(),这是没有委托的代码看起来的样子(你需要让TheOtherClass知道你的myFactory的类型):
TheOtherClass toc;
//...
toc.SetFactory(myFactory);
class TheOtherClass
{
public void SetFactory(MyFactory factory)
{
// set here
}
}
如果你使用委托,你不需要暴露我的工厂的类型:
TheOtherClass toc;
//...
Action factoryMethod = myFactory.GetInstance;
toc.SetFactoryMethod(factoryMethod);
class TheOtherClass
{
public void SetFactoryMethod(Action factoryMethod)
{
// set here
}
}
因此,您可以将委托交给其他类使用,而无需向它们暴露您的类型。你唯一要暴露的是你的方法的签名(你有多少参数等等)。
"我的方法的签名"我在哪儿听过这个?哦,是的,接口!!接口描述了整个类的签名。把委托看作是只描述一个方法的签名!
接口和委托之间的另一个巨大区别是,当你编写类时,你不必对c#说“这个方法实现了那种类型的委托”。对于接口,你确实需要说“这个类实现了那种类型的接口”。
此外,一个委托引用可以(有一些限制,见下文)引用多个方法(称为MulticastDelegate)。这意味着当您调用委托时,将执行多个显式附加的方法。一个对象引用总是只能引用一个对象。
MulticastDelegate的限制是(方法/委托)签名不应该有任何返回值(void),关键字out和ref不能在签名中使用。显然,您不能调用两个返回一个数字的方法,并期望它们返回相同的数字。一旦签名符合要求,该委托就自动成为MulticastDelegate。
事件
事件只是属性(就像get;set;属性到实例字段),这将从其他对象向委托公开订阅。但是,这些属性不支持get;set;。相反,它们支持add;删除;
所以你可以有:
Action myField;
public event Action MyProperty
{
add { myField += value; }
remove { myField -= value; }
}
在UI中的使用(WinForms,WPF,UWP等等)
So, now we know that a delegate is a reference to a method and that we can have an event to let the world know that they can give us their methods to be referenced from our delegate, and we are a UI button, then: we can ask anyone who is interested in whether I was clicked, to register their method with us (via the event we exposed). We can use all those methods that were given to us and reference them by our delegate. And then, we'll wait and wait.... until a user comes and clicks on that button, then we'll have enough reason to invoke the delegate. And because the delegate references all those methods given to us, all those methods will be invoked. We don't know what those methods do, nor we know which class implements those methods. All we do care about is that someone was interested in us being clicked, and gave us a reference to a method that complied with our desired signature.
Java
像Java这样的语言没有委托。相反,他们使用接口。他们这样做的方式是让任何对“我们被点击”感兴趣的人来实现某个接口(使用我们可以调用的某个方法),然后给我们实现该接口的整个实例。我们保留了实现该接口的所有对象的列表,并在我们被单击时调用它们的“我们可以调用的特定方法”。
我对这些事件的理解是;
委托:
保存要执行的方法/方法的引用的变量。这使得像传递变量一样传递方法成为可能。
创建和调用事件的步骤:
事件是委托的实例 由于事件是委托的实例,因此我们必须首先定义委托。 指定在事件触发时执行的方法/方法(调用委托) 触发事件(调用委托)
例子:
using System;
namespace test{
class MyTestApp{
//The Event Handler declaration
public delegate void EventHandler();
//The Event declaration
public event EventHandler MyHandler;
//The method to call
public void Hello(){
Console.WriteLine("Hello World of events!");
}
public static void Main(){
MyTestApp TestApp = new MyTestApp();
//Assign the method to be called when the event is fired
TestApp.MyHandler = new EventHandler(TestApp.Hello);
//Firing the event
if (TestApp.MyHandler != null){
TestApp.MyHandler();
}
}
}
}
要理解事件处理程序,您需要理解委托。在c#中,您可以将委托视为指向方法的指针(或引用)。这很有用,因为指针可以作为值传递。
委托的核心概念是它的签名或形状。即(1)返回类型和(2)输入参数。例如,如果我们创建一个委托void MyDelegate(object sender, EventArgs e),它只能指向返回void的方法,并接受一个对象和EventArgs。有点像一个方洞和一个方钉子。因此,我们说这些方法与委托具有相同的签名或形状。
So knowing how to create a reference to a method, let's think about the purpose of events: we want to cause some code to be executed when something happens elsewhere in the system - or "handle the event". To do this, we create specific methods for the code we want to be executed. The glue between the event and the methods to be executed are the delegates. The event must internally store a "list" of pointers to the methods to call when the event is raised.* Of course, to be able to call a method, we need to know what arguments to pass to it! We use the delegate as the "contract" between the event and all the specific methods that will be called.
因此默认的EventHandler(以及许多类似的)表示方法的特定形状(同样是void/object-EventArgs)。当你声明一个事件时,你是在说该事件将调用哪种形状的方法(EventHandler),通过指定一个委托:
//This delegate can be used to point to methods
//which return void and take a string.
public delegate void MyEventHandler(string foo);
//This event can cause any method which conforms
//to MyEventHandler to be called.
public event MyEventHandler SomethingHappened;
//Here is some code I want to be executed
//when SomethingHappened fires.
void HandleSomethingHappened(string foo)
{
//Do some stuff
}
//I am creating a delegate (pointer) to HandleSomethingHappened
//and adding it to SomethingHappened's list of "Event Handlers".
myObj.SomethingHappened += new MyEventHandler(HandleSomethingHappened);
//To raise the event within a method.
SomethingHappened("bar");
(*这是。net中事件的关键,它揭开了“魔法”的面纱——一个事件实际上只是一组具有相同“形状”的方法。列表存储在事件所在的位置。当事件被“引发”时,它实际上只是“遍历这个方法列表并调用每个方法,使用这些值作为参数”。分配事件处理程序只是将您的方法添加到要调用的方法列表的一种更漂亮、更简单的方式)。