C# 为什么我们需要“一个”呢;事件“;定义事件时使用关键字?
我不明白为什么我们在定义事件时需要“event”关键字,而我们可以不用“event”关键字做同样的事情,只需使用委托 e、 gC# 为什么我们需要“一个”呢;事件“;定义事件时使用关键字?,c#,.net,C#,.net,我不明白为什么我们在定义事件时需要“event”关键字,而我们可以不用“event”关键字做同样的事情,只需使用委托 e、 g 在这里,如果我从第二行中删除“event”关键字,那么我也可以通过调用委托来引发事件。有人能告诉我为什么需要这个事件关键字吗?这部分是需要的,因为如果省略事件关键字,就会破坏封装。如果它只是一个公共多播委托,任何人都可以调用它,将其设置为null或篡改它。如果存在一个名为MailNotifier的类,并且它有一个名为MailReceived的事件,则其他类型无法通过调用
在这里,如果我从第二行中删除“event”关键字,那么我也可以通过调用委托来引发事件。有人能告诉我为什么需要这个事件关键字吗?这部分是需要的,因为如果省略
事件
关键字,就会破坏封装。如果它只是一个公共多播委托,任何人都可以调用它,将其设置为null或篡改它。如果存在一个名为MailNotifier
的类,并且它有一个名为MailReceived
的事件,则其他类型无法通过调用MailNotifier.MailReceived()
触发该事件
另一方面,您只能从定义它的类型中处理和调用“类似于字段”的事件
如果您想保持事件调用的私密性,那么没有什么可以阻止您这样做:
public class MyClassWithNonFieldLikeEvent
{
private CustomEventHandler m_delegate;
public void Subscribe(CustomEventHandler handler)
{
m_delegate += handler;
}
public void Unsubscribe(CustomEventHandler handler)
{
m_delegate -= handler;
}
private void DoSomethingThatRaisesEvent()
{
m_delegate.Invoke(...);
}
}
。。。但这只是为了(或多或少)完成类似于字段的事件已经提供给我们的全部代码。与委托字段相比,事件具有明显的优势。与字段相比,事件可以在接口中定义,从而为代码添加了抽象,更重要的是:只能从定义类内部调用事件。在您的情况下,任何人都可以调用该事件,可能会破坏您的代码
有关更多信息,请参阅。事件关键字执行3种不同的操作:
=
和()
操作符(赋值和调用)的可见性更改为private,以便只有包含类可以调用事件或覆盖其中包含的所有方法。-=
和+=
操作符仍然可以在定义事件的类之外的事件上调用(它们获取您在事件旁边编写的访问修饰符)-=
和+=
在事件上的行为方式类似于字段的事件和委托类型的公共字段看起来相似,但实际上非常不同 事件基本上类似于属性——它是一对添加/删除方法(而不是属性的get/set)。当您声明一个类似于字段的事件(即您自己没有指定添加/删除位的事件)时,将创建一个公共事件和一个私有备份字段。这允许您私下引发事件,但允许公开订阅。使用公共委托字段,任何人都可以删除其他人的事件处理程序,自己引发事件,等等-这是一个封装灾难
有关活动(和代表)的更多信息,请阅读我的。(在某个时候,我需要为C#4更新它,它会像事件一样轻微地改变字段。尽管它的要点仍然是正确的。)其他答案都很好;我只想补充一点思考 您的问题是“当我们有委托类型的字段时,为什么我们需要事件?”我想扩展这个问题:如果您有委托类型的字段,为什么您需要方法、属性、事件、实例构造函数或终结器?除了在类型中包含值和委托的字段之外,为什么还需要其他内容?为什么不直接说呢
class C
{
private int z;
public readonly Func<int, int> M = (int x)=>{ return x+z; }
// ... and so on
}
C类
{
私人INTZ;
公共只读函数M=(int x)=>{return x+z;}
//……等等
}
?
您不需要方法、属性或事件。我们提供这些东西是因为方法、属性和事件设计模式非常重要和有用,应该有一个标准的、有文档记录的、清晰的方法来用这种语言实现它们 是一种引用类型。它继承了。是一个修饰语。是委托的特殊修饰符。它修改了一些函数/方法的可访问性,例如Invoke方法。在被修饰符事件修改后,委托实例成为一个新概念“事件”。所以事件只是一个修改过的委托。您不能在定义事件的类之外直接更改引用或调用事件,但可以更改引用或调用普通委托实例。事件提供额外的保护,使事件具有更多的安全功能。
当您在定义事件的类之外时,允许您对事件执行两种类型的操作,“+=”和“-=”。
但是您可以访问普通委托实例的所有公共字段、属性、方法等。
以下是一个例子:
namespace DelegateEvent
{
//下面这行的行为就像一个类。它确实是一个引用类型
公共委托void MyDelegate(字符串输入);
//以下行是非法的。它只能是一个实例。因此它不能直接位于命名空间下
//公共事件MyEvent;
公共类MyClassA
{
公共活动代表MyEventA;
公共MyDelegate MyDelegateA;
System.Threading.ManualResetEvent MyResetEvent=新的System.Threading.ManualResetEvent(错误);
公共无效TryToDoSomethingOnMyDelegateA()
{
如果(MyDelegateA!=null)
{
//用户可以assecc所有公共方法。
MyDelegateA(“我可以在classA中调用detegate”);//调用委托
调用(“我可以在类A中调用detegate”);//调用委托
IAsyncResult result=MyDelegateA.BeginInvoke(“我可以在类A中调用detegate”,MyAsyncCallback,MyResetEvent);//异步调用
//用户可以检查委托实例的公共属性和字段
System.Reflection.MethodInfo delegateAMethodInfo=MyDelegateA.Method;
MyDelegateA=testMethod;//重置引用
MyDelegateA=新的MyDelegate(testMethod);//重置引用
MyDelegateA=null;
class C
{
private int z;
public readonly Func<int, int> M = (int x)=>{ return x+z; }
// ... and so on
}