简体   繁体   English

在C#中将lambda表达式或匿名函数转换为委托对象的最直接方法是什么?

[英]What is the most direct way of transforming a lambda expression or anonymous function into a Delegate Object in C#?

I am writing some code to solve thread-safe issues in a system am working on, and one of the recommended approaches is to use delegates to solve cross-thread issues. 我正在编写一些代码来解决正在处理的系统中的线程安全问题,推荐的方法之一是使用委托来解决跨线程问题。 But for some reason, I don't like having to define a delegate for every possible operation i might have to intercept, and thus prefer working with anonymous methods or lambda expressions, but I the compiler refuses to cast any of these to a System.Delegate object. 但是由于某些原因,我不喜欢为每个可能要拦截的操作定义一个委托,因此更喜欢使用匿名方法或lambda表达式,但是我编译器拒绝将其中的任何一个强制转换为System。委托对象。

Is there a shortcut to this? 这有什么捷径吗?

if (someListBox.InvokeRequired) if(someListBox.InvokeRequired)
{ {
someListBox.Invoke(Some_System.Delegate_Object, new object[] {item}); someListBox.Invoke(Some_System.Delegate_Object,新对象[] {item});
} }
else 其他
someListBox.Items.Add(item); someListBox.Items.Add(项目);

I want something like... 我想要像......

if (someListBox.InvokeRequired) if(someListBox.InvokeRequired)
{ {
someListBox.Invoke((i) => { someListBox.Items.Add(i); }, new object[] {item}); someListBox.Invoke((i)=> {someListBox.Items.Add(i);},新对象[] {item});
} }
else 其他
someListBox.Items.Add(item); someListBox.Items.Add(项目);

One of your problems is that the compiler can't infer the parameter types of your lamda. 您的一个问题是编译器无法推断您的lamda的参数类型。 And even for a given parameter signature there are infinitely many potential delegate types. 即使对于给定的参数签名,也存在无限多的潜在委托类型。 So you need to explicitly give a type. 因此,您需要显式地指定类型。 Action<...> and Func<...> are typical candidates if you don't care about parameter names. 如果您不关心参数名称, Action<...>Func<...>是典型的候选者。

I think this should work: 我认为这应该有效:

`someListBox.Invoke((Action<int>)((i) => {listviewResults.Items.Add(i); }), new object[] {item});`

Or in refactored form to avoid repeating yourself: 或采用重构形式以避免重复自己:

Action<int> myAction=(i) => listviewResults.Items.Add(i);
if (someListBox.InvokeRequired)
{
    someListBox.Invoke( myAction, new object[] {item});
}
else
    myAction(item);

And I see no reason why you'd want to have i as a parameter at all: 而且我认为你没有理由想让i作为一个参数:

Action myAction = () => listviewResults.Items.Add(item);
if (someListBox.InvokeRequired)
{
    someListBox.Invoke( myAction );
}
else
    myAction();

The downside with the approach that you want is that the actual work will be implemented in two places. 所需方法的缺点是实际工作将在两个地方进行。 One alternative approach might look like this: 一种替代方法可能如下所示:

private void AddItemToListView(ListViewItem item, ListView listView)
{
    if (listView.InvokeRequired)
    {
        listView.BeginInvoke((Action)delegate { AddItemToListView(item, listView); });
    }
    else
    {
        listView.Items.Add(item);
    }
}

Then again, you could debate how often this code is executed. 再说一次,您可以讨论该代码执行的频率。 If it is not extremely much, perhaps its better to simplify it a bit by not checking for InvokeRequired , but rather always wrap the call in a delegate passed to BeginInvoke : 如果不是非常多,最好不检查InvokeRequired来简化它,而应始终将调用包装在传递给BeginInvoke

private void AddItemToListView(ListViewItem item, ListView listView)
{
    listView.BeginInvoke((Action)delegate { listView.Items.Add(item); });       
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM