委托、事件 茴字有几种写法

作用

可以将方法作为变量

委托与事件最大的作用其实就是可以让方法(函数)成为一个变量,然后再外部实例化这个类时定义这个方法。但是方法不属于基本类型,不能像定义普通变量一样的去声明它,如我们可以定义一个速度变量

public int speed{get;set;}

。但是不能定义一个方法

public 求距离的方法 GetDistince{get;set;}

我们需要先定义个委托类型 public delegate void 求距离的方法(DateTime dt);

然后才可以写      public 求距离的方法 GetDistince;

这样就很麻烦,微软为了解决这个问题就发明了事件、和预定义了Action<> Func<>等委托。然后为了简化事件的写法。接着发明了 事件.Invoke 等方法。所以现在,我们要想将一个类的方法在实例化时定义,就有很多种写法。

不用委托的代码

public static  void main()
{
     console.write("程序要做的事");  
     console.write("程序要做的事");  
     console.write("程序要做的事");  
     console.write("程序要做的事");  
}

封装

后面我发现其他地方也要用到相同的功能,所以我想封装下,将程序要做的事写在另一个类中。

public static  void main()
{
    common.DoSomeThing();
}
public class common
{
   public static void DoSomeThing()
    {
     Console.Write("程序要做的事");  
     Console.Write("程序要做的事");  
     Console.Write("程序要做的事");  
     Console.Write("程序要做的事");  
    }
} 

委托解决的问题:方法可变,可能有多个类似的方法

然后我们发现程序要做的事有部分不一样,所以我们希望由main函数可以设置doSomeThing中执行什么函数。

我们用到的可能doSomeThing可能有下面两个版本

   public static void DoSomeThing1()
    {
     console.write("程序要做的事");  
     console.write("程序要做的事");  
     console.write("程序要做的事");  
     console.write("程序要做的特殊事情1");  
    }
   public static void DoSomeThing2()
    {
     console.write("程序要做的事");  
     console.write("程序要做的事");  
     console.write("程序要做的事");  
     console.write("程序要做的特殊事情2");  
    }

使用委托

这样就很不好看,也不利于扩展,所以可以引入委托,这样我们可以在执行的时候自己选择执行什么特殊方法。

    class Program
    {
        static void Main(string[] args)
        {
            //指定特殊的那段程序执行什么
            common.doSomeThingSpeical += common.DoSomeThingSpeical1;
            common.DoSomeThing();
        }
    }
    public class common
    {
        public delegate void DoSomeThingSpeicaldelegate();
        public static DoSomeThingSpeicaldelegate doSomeThingSpeical;
        public static void DoSomeThing()
        {
            Console.Write("程序要做的事");
            Console.Write("程序要做的事");
            Console.Write("程序要做的事");
            if (doSomeThingSpeical != null)
            {
                doSomeThingSpeical();
            }
            Console.ReadKey();
        }
        public static void DoSomeThingSpeical1()
        {
            Console.Write("程序要做的独特的事1");
        }
        public static void DoSomeThingSpeical2()
        {
            Console.Write("程序要做的独特的事2");
        }
    }

如果既不想用DoSomeThingSpeical1也不想用DoSomeThingSpeical2,那么可以在调用的时候自己写一个DoSomeThingSpeical3,然后给common.doSomeThingSpeical赋值。

class Program
    {
        static void Main(string[] args)
        {
            //指定特殊的那段程序执行什么
            common.doSomeThingSpeical += DoSomeThingSpeical3;
            common.DoSomeThing();
        }

        public static void DoSomeThingSpeical3()
        {
            Console.Write("程序要做的独特的事3");
        }
    }

以上就是委托的基本使用了

预定义的委托

可以看到,我们要将方法作为变量时,需要先定义一个委托,很麻烦,所以微软后来为我们预定义了一些委托(Action Func 等),我们不用声明这个委托就可以直接用他们做变量。
 如,上面我们写的:
        public delegate void DoSomeThingSpeicaldelegate();
        public static DoSomeThingSpeicaldelegate doSomeThingSpeical;

可以直接简化为:
        public static Action doSomeThingSpeical;

同样这个也可以写成event的形式,事件的实现要稍微复杂一点,这个例子虽然能改成event的形式,但是说明不了event的应用场景,对event我还需要深入学习体会。

匿名方法

仔细想了下,我觉得还是要先说说匿名方法

在上面的例子中,我们Main函数定义委托时,我们不想定义一个方法,再赋值,这时就可以用匿名方法,直接就可以写方法体而不需要申明这个方法。

    class Program
    {
        static void Main(string[] args)
        {
            //指定特殊的那段程序执行什么
            common.doSomeThingSpeical += delegate(){
            Console.Write("程序要做的独特的事3");
            };
            common.DoSomeThing();
        }

        //public static void DoSomeThingSpeical3()
        //{
        //    Console.Write("程序要做的独特的事3");
        //}
    }

事件

 

    class Program
    {
        static void Main(string[] args)
        {
            var Test = new Test();
            void eventHandler(object s, EventArgs e)
            {
                Console.WriteLine("1");
            }
            void eventHandler2(object s, EventArgs e)
            {
                Console.WriteLine("2");
            }
            void eventHandler3(object s, EventArgs e)
            {
                Console.WriteLine("3");
            }
            void eventHandler4(object s, EventArgs e)
            {
                Console.WriteLine("4");
            }

            //添加事件
            Test.A += eventHandler;
            Test.EventHandlers.Add(eventHandler2);
            Test.Actions.Add(eventHandler3);
            Test.B += eventHandler4;

            Test.Run();

            //移除事件
            Test.A -= eventHandler;
            Test.EventHandlers.Remove(eventHandler2);
            Test.Actions.Remove(eventHandler3);
            Test.B -= eventHandler4;
            Console.ReadKey();
        }
    }
    public class Test
    {
        public List<EventHandler> EventHandlers { get; set; } = new List<EventHandler>();
        public event EventHandler A
        {
            add
            {
                EventHandlers.Add(value);
            }
            remove
            {
                EventHandlers.Remove(value);
            }
        }

        public List<Action<object, EventArgs>> Actions { get; set; } = new List<Action<object, EventArgs>>();
        public event Action<object, EventArgs> B
        {
            add
            {
                Actions.Add(value);
            }
            remove
            {
                Actions.Remove(value);
            }
        }

        public void Run()
        {
            EventArgs e = new EventArgs();
            foreach (var eventHandler in EventHandlers)
            {
                eventHandler.Invoke("Test", e);
            }

            foreach (var action in Actions)
            {
                action.Invoke("Test2", e);
            }
        }
    }
示例

 

posted @ 2017-03-12 00:23  胡正  阅读(499)  评论(0编辑  收藏  举报