我们可以创建一个不像字段的事件吗?

时间:2015-03-09 16:35:53

标签: c# events

在深度的C#中,Jon Skeet说:

  

开发人员经常混淆事件和委托实例,或者用委托类型声明的事件和字段。

在阅读了他的解释后,我了解得更多,尽管我仍然对事件究竟是什么感到困惑。从下面的代码中,看起来所有事件都是约束一个类必须委托另一个类中的字段的访问权限。

  

...你经常不希望类外的代码能够任意改变(或调用)事件的处理程序... [so]编译器将声明转换为默认add /的事件删除实现和相同类型的私有字段。

换句话说,由于访问控制,事件与委托不同。或者这仅仅是乔恩称之为“田野般的事件”?

  • 类似字段的事件是否与事件不同?
  • C#中的事件是否总是像字段一样,还是我们还可以创建非字段的事件?
  • 事件和类似字段的事件之间有什么区别?

换句话说,C#是否同时支持事件和类似字段的事件,还是这两种说法相同?

代码示例https://dotnetfiddle.net/7fOwvb

using System;
using System.Reflection;

public delegate void TheDelegate(string message);
public static class Program
{
    public static event TheDelegate TheEvent;
    public static TheDelegate DelInstance;
    public static void Main()
    {
        DelInstance = new TheDelegate(TheMethod);
        DelInstance += TheMethod;
        DelInstance.Invoke("Invoke the delegate.");
        PrintMemberInfo(DelInstance.GetType());

        TheEvent += TheMethod;
        TheEvent += TheMethod;
        TheEvent.Invoke("Invoke the event.");
        PrintMemberInfo(TheEvent.GetType());        

        new AnotherClass();
    }

    // Create a method for a delegate. 
    public static void TheMethod(string message)
    {
        Console.WriteLine(message);
    }

    public static void PrintMemberInfo(System.Type t)
    {
        foreach (MemberInfo m in t.GetMembers())
        {
            Console.Write(m.Name + ", ");
        }
        Console.WriteLine("\n");
    }
}

public class AnotherClass
{
    public AnotherClass()
    {
        Program.DelInstance += new TheDelegate(AnotherMethod);
        Program.DelInstance.Invoke("Another class");

        // Error... we can only call += or -+
        // Program.TheEvent.Invoke();
    }

    public void AnotherMethod(string message)
    {
        Console.WriteLine(message);
    }
}

1 个答案:

答案 0 :(得分:3)

类似字段的事件是相当于自动属性的事件,即具有编译器生成的add / remove访问器的事件。

  

类似字段的活动

     

在包含事件声明的类或结构的程序文本中,某些事件可以像字段一样使用。要以这种方式使用,事件不能是抽象的或外部的,并且不能明确包含事件访问器声明。这样的事件可以在允许字段的任何上下文中使用。该字段包含一个委托(第15节),该委托引用已添加到事件的事件处理程序列表。如果未添加事件处理程序,则该字段包含null。

     

(C#5.0规范)

您可以在C#中使用自定义访问者(addremove)实现事件。

event EventHandler IDrawingObject.OnDraw
{
    add
    {
        ...
    }
    remove
    {
        ...
    }
}

请参阅How to: Implement Custom Event Accessors (C# Programming Guide)