zoukankan      html  css  js  c++  java
  • 关于委托:异常{ 无法将 匿名方法 转换为类型“System.Delegate”,因为它不是委托类型 }

    异常{ 无法将 匿名方法 转换为类型“System.Delegate”,因为它不是委托类型 }

    委托实际上是把方法名作为参数,但是若有好多个方法时,就要指明是哪个参数 

    查看如下代码:
    this.Invoke(delegate
                    {
                        MessageBox.Show("t4");
                    });
    熟悉winform的开发者都知道,this是一个窗体的实例,故不做另外解释。该代码的运行,就会导致异常:{ 无法将 匿名方法 转换为类型“System.Delegate”,因为它不是委托类型 }。

    其实,要从错误的提示信息来看,这个匿名方法写的是一点问题都没有的。问题的关键是invoke这个函数的参数,我们查看其原型为:
    public object Invoke(Delegate method)
    也就说,它所接受的是一个Delegate,那么,任何一个派生自Delegate的实例,都是可被接受的。我们知道,类似ThreadStart,MethodInvoker都派生自Delegate,那么编译器在转化这个匿名函数的时候,就不知道要将这个匿名函数转为ThreadStart还是MethodInvoker,于是报错。(代表一个委托函数的,还有ParameterizedThreadStart、WaitCallback、AsyncCallback等,只不过他们都是带有参数的。)
    正确的语法应该如下:
    this.Invoke(new MethodInvoker(delegate { MessageBox.Show("t3"); }));
            或者
    this.Invoke((ThreadStart)delegate
                    {
                        MessageBox.Show("t4");
                    });
    这样,编译器就知道要将匿名函数转化为哪个参数了。
    题外话:注意这里,无论是new还是转型,都是一样的。

    现将各类语法总结如下:
    private void button1_Click(object sender, EventArgs e)
            {
                //将delegate转为ThreadStart
                Thread t1 = new Thread((ThreadStart)delegate { MessageBox.Show("t1"); });
                t1.Start();
                //将delegate转为ThreadStart的第二种写法
                Thread t2 = new Thread(new ThreadStart(delegate() { MessageBox.Show("t2"); }));
                t2.Start();
                //将delegate转为MethodInvoker
                this.Invoke(new MethodInvoker(delegate { MessageBox.Show("t3"); }));
                //将delegate转为ThreadStart
                this.Invoke((ThreadStart)delegate
                    {
                        MessageBox.Show("t4");
                    });
                //将delegate转为WaitCallback
                ThreadPool.QueueUserWorkItem((WaitCallback)delegate
                {
                    MessageBox.Show("t5");
                });
                //默认将delegate转为WaitCallback,因为QueueUserWorkItem只接受WaitCallback参数
                ThreadPool.QueueUserWorkItem(delegate
                    {
                        MessageBox.Show("t5");
                    });
                WaitCallback wc = new WaitCallback(this.DoSomethingWithState);
                ThreadPool.QueueUserWorkItem(wc, "i am state.");
            }

            void DoSomethingWithState(Object c)
            {
                MessageBox.Show("t6" + c.ToString());
            }

    最后,附上几个Delegate的原型:
    public delegate void ThreadStart();
    public delegate void MethodInvoker();
    public delegate void WaitCallback(object state);
    public delegate void ParameterizedThreadStart(object obj);
    public delegate void AsyncCallback(IAsyncResult ar);

  • 相关阅读:
    Java实现 蓝桥杯 算法提高 特等奖学金(暴力)
    Java实现 蓝桥杯 算法提高 特等奖学金(暴力)
    Java实现 蓝桥杯 算法提高 GPA(暴力)
    Java实现 蓝桥杯 算法提高 GPA(暴力)
    Java实现 蓝桥杯 算法提高 GPA(暴力)
    Java实现 蓝桥杯 算法提高 套正方形(暴力)
    Java实现 蓝桥杯 算法提高 套正方形(暴力)
    第一届云原生应用大赛火热报名中! helm install “一键安装”应用触手可及!
    云原生时代,2个方案轻松加速百万级镜像
    Knative 基本功能深入剖析:Knative Serving 自动扩缩容 Autoscaler
  • 原文地址:https://www.cnblogs.com/liulaocai2/p/4383494.html
Copyright © 2011-2022 走看看