zoukankan      html  css  js  c++  java
  • delegate and Delegate

    // The following line causes the compiler to generate

    // a new delegate class named CheckAndPrintDelegate that

    // inherits from System.MulticastDelegate.

    public delegate void CheckAndPrintDelegate(string str);

     

    MulticastDelegate is a special class. Compilers can derive from this class, but you cannot derive from it explicitly. The same is true of the Delegate class. Both of them are abstract class, MulticastDelegate derives from Delegate.

    event is a special delegate.

    Below is a sample.

    public partial class MainWindow : Window

    {

    public MainWindow()

    {

    InitializeComponent();

    }

    static void Handler1(object sender, EventArgs e)

    {

    Console.WriteLine("Handler1");

    }

    static void Handler2(object sender, EventArgs e)

    {

    Console.WriteLine("Handler2");

    throw new InvalidOperationException();

    }

    static void Handler3(object sender, EventArgs e)

    {

    Console.WriteLine("Handler3");

    }

    private void button1_Click(object sender, RoutedEventArgs e)

    {

    // below is a CreateDelegate test. create a delegate instance named "CreateDelegateTest" of delegate type Action<string>).

    Delegate d = Delegate.CreateDelegate(typeof(Action<string>), new Target(), "CreateDelegateTest");

    Action<string> a = (Action<string>)d;

    a("a test string");

    // below is test of dynamic invoke.

    EventSource source = new EventSource();

    source.TheEvent += Handler1;

    source.TheEvent += Handler2;

    source.TheEvent += Handler3;

    try

    {

    source.RaiseEvent1();

    }

    catch (Exception ex)

    {

    Console.WriteLine(ex.Message);

    }

    Console.WriteLine("-------------------");

    source.RaiseEvent2();

    // below test Delegate.Combine.

    // Delegate.Combine is the internal implementation of +=, += in code will be compiled to call Combine by the compiler.

    var combinedDs = Delegate.Combine(new EventHandler(Handler1), new EventHandler(Handler2),new EventHandler(Handler3));

    ((EventHandler)combinedDs)(this, EventArgs.Empty);

    }

    }

    public class Target

    {

    public void CreateDelegateTest(string str)

    {

    Console.WriteLine(str);

    }

    }

    // One of the things the Delegate class can be used for is more control when invoking event handlers.

    // For example, with normal event processing, an exception in any event handler will prevent

    // any later event handlers from being called. You can alter that behavior by using the Delegate class

    // to manually invoke each event handler.

    class EventSource

    {

    public event EventHandler TheEvent;

    internal void RaiseEvent1()

    {

    EventHandler handler = TheEvent;

    if (handler != null)

    handler(this, EventArgs.Empty);

    }

    internal void RaiseEvent2()

    {

    EventHandler handler = TheEvent;

    if (handler == null)

    return;

    // gets the invocation list of this multicast delegate.

    Delegate[] handlers = handler.GetInvocationList();

    foreach (Delegate d in handlers)

    {

    object[] args = new object[] { this, EventArgs.Empty };

    try

    {

    //Dynamically invokes (late-bound) the method represented by the current delegate.

    d.DynamicInvoke(args);

    }

    catch (Exception ex)

    {

    while (ex.InnerException != null)

    {

    ex = ex.InnerException;

    Console.WriteLine(ex.Message);

    }

    }

    }

    }

    }

     

    event和delegate的区别和关系:

    首先,通过加入event关键字,在编译的时候编译器会自动针对事件生成一个私有的字段(与此事件相关的委托),以及两个访问器方法,即add访问器方法以及

    remove访问器方法,用于对事件的注册及注销(对事件使用+=及-=操作时就是调用的这两个方法)。

    实际上之所以采用event而不直接采用委托,实际上还是为了封装。可以设想一下,如果直接采用公共的委托字段,类型外部就可以对此字段进行直接的操作了,比

    如将其直接赋值为null。而使用event关键字就可以保证对事件的操作仅限于add访问器方法以及remove访问器方法(即只能使用+=及-=)。

    另外事件主要是为了实现一种通知机制,当某个事件发生是,外部可以注册这个事件来做相应的事情。
    event与delegate是C#中的两个关键字,在微软的例程中常见它们一起出现,那么他们之间有什么关系呢?

    例如下面的代码:
    public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();

                ClickEvent += new EventHandler(MainWindow_ClickEvent1);  // called it A
                ClickEvent += new EventHandler(MainWindow_ClickEvent2);  // called it B
                var list1 = ClickEvent.GetInvocationList(); // list1: A, B
                // you can remove one.
                ClickEvent = ClickEvent - new EventHandler(MainWindow_ClickEvent2);
                var list2 = ClickEvent.GetInvocationList(); // list2: A

                ClickDelegate = (EventHandler)(Delegate.Combine(new EventHandler(MainWindow_ClickEvent1), new EventHandler

    (MainWindow_ClickEvent2)));
                var list3 = ClickDelegate.GetInvocationList(); // list3: A, B
                ClickDelegate = (EventHandler)(Delegate.Remove(ClickDelegate, new EventHandler(MainWindow_ClickEvent2)));
                var list4 = ClickDelegate.GetInvocationList(); // list4: A
            }

            void MainWindow_ClickEvent1(object sender, EventArgs e)
            {
                
            }

            void MainWindow_ClickEvent2(object sender, EventArgs e)
            {

            }

            public event EventHandler ClickEvent;
            public EventHandler ClickDelegate;
        }
    通过ildasm查看,我们可以看到生成的ClickEvent和ClickDelegate两个Delegate, 他们的类型都是EventHandler。
    例如还有add和remove两个访问器方法:

    双击add_ClickEvent:
      IL_000b:  call       class [mscorlib]System.Delegate [mscorlib]System.Delegate::Combine(class [mscorlib]System.Delegate,
                                                                                              class [mscorlib]System.Delegate)
    同理双击remove_ClickEvent:
      IL_000b:  call       class [mscorlib]System.Delegate [mscorlib]System.Delegate::Remove(class [mscorlib]System.Delegate,
                                                                                             class [mscorlib]System.Delegate)

    也就是说,实际上,添加一个事件的绑定,实际上就是向该事件表示的委托列表中添加一项委托。而取消一个事件的绑定,就是从委托列表中删除一项委托。
    所以,对event的绑定都是通过在delegate列表中添加、删除项来实现的,所以就有了示例代码中的操作。
    另外,需要注意的一点是:除了在event对象声明的类内部,event对象只能用在+=和-=的左边。

  • 相关阅读:
    js实现倒计时
    CSS解决ul下面最后一个li的margin
    js手动定时清除localStorage
    js应用中的小细节-时间戳的转换和input输入框有效数字
    javaScript将string转换成array,并将汉字按汉语拼音排序方法
    CSS3属性之text-overflow:ellipsis,指定多行文本中任意一行显示...
    移动端下拉刷新,向后台请求数据
    进程 线程 协程
    网络编程
    flask 2 进阶
  • 原文地址:https://www.cnblogs.com/bear831204/p/2117001.html
Copyright © 2011-2022 走看看