Code Bye

何时可以直接用“ lambda 表达式”作为委托参数

前两个例子是可以的,但后一个例子就不行

static void Main(string[] args)
{
    int[] a = { 8, 2, 6, 56, 46, 18 };
    Func<int, bool> d = i => i > 18; //Func委托,返回所给整数参数的值是否大于18
    bool b = a.Any(d);//数组中有大于18的数据吗?
    Console.WriteLine(b);
}

可简写成:

static void Main(string[] args)
{
    int[] a = { 8, 2, 6, 56, 46, 18 };
    bool b = a.Any(i => i > 18); // Any是个“扩展方法”
    Console.WriteLine(b);
}

下面是Func委托的定义
public delegate TResult Func<in T, out TResult>(T arg);

再比如:

class Program
{
    static void Main(string[] args)
    {
        ThreadStart ts=new ThreadStart(Run);            
        Thread t = new Thread(ts);
        t.Start();
    }
    static void Run()
    {
        for (int i = 0; i < 1000; ++i)
        {
            Console.WriteLine(i);
        }
    }
}

我也可以简写成:

static void Main(string[] args)
{
    Thread t = new Thread(() =>
    {
        for (int i = 0; i < 1000; ++i)
        {
            Console.WriteLine(i);
        }
    });
    t.Start();
}

这是ThreadStart委托的定义
public delegate void ThreadStart();

都可以直接用“lambda 表达式”作为委托参数,但下面的却不行:
在多线程中更新用户界面时,需要调用Invoke方法来更新用户界面,比如:

public partial class Form1 : Form
{
    private delegate void UpdateUIDelegate(int i);
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Thread t=new Thread(doWorker);
        t.Start();
    }
   private void UpdateUI(int i)
    {
        label1.Text = i.ToString();
    }

    private void doWorker()
    {
        UpdateUIDelegate ui = UpdateUI;
        for (int i = 0; i < 1000; ++i)
        {
            label1.Invoke(ui, i);
            Thread.Sleep(10);
        }
    }
}

我想简写成下面的样子:

public partial class Form1 : Form
{
    private delegate void UpdateUIDelegate(int i);
    public Form1()
    {
        InitializeComponent();
    }
    private void button1_Click(object sender, EventArgs e)
    {
        Thread t=new Thread(doWorker);
        t.Start();
    }

    //private void UpdateUI(int i)
    //{
    //    label1.Text = i.ToString();
    //}
    private void doWorker()
    {
        for (int i = 0; i < 1000; ++i)
        {
            label1.Invoke(n => { label1.Text = n.ToString(); }, i); //***出现错误***
            Thread.Sleep(10);
        }
    }
}

却出现错误错误:
无法将 lambda 表达式 转换为类型“System.Delegate”,因为它不是委托类型
但若写成下面的,就没问题了:
label1.Invoke((UpdateUIDelegate)(n => { label1.Text = n.ToString(); }), i);

Invoke的参数如下:
public object Invoke(Delegate method, params object[] args);

和前面不同的是这里的参数是Delegate

我查阅了一些资料,说delegate定义的委托派生自MulticastDelegate,而MulticastDelegate又派生自Delegate,Delegate又派生自object.

我们都知道:
object obj=25;//不需要强制类型转换
int i=(int)object;//需要强制类型转换

Invoke的参数是Delegate,是其他委托的基类,为何这里还需要强制类型转换呢?
—-


CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明何时可以直接用“ lambda 表达式”作为委托参数