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

发布于 2024-10-11 07:36:20 字数 607 浏览 3 评论 0原文

我正在编写一些代码来解决正在处理的系统中的线程安全问题,推荐的方法之一是使用委托来解决跨线程问题。但出于某种原因,我不喜欢为我可能必须拦截的每个可能的操作定义委托,因此更喜欢使用匿名方法或 lambda 表达式,但编译器拒绝将其中任何一个强制转换为 System.委托对象。

这有捷径吗?

if (someListBox.InvokeRequired)
{
someListBox.Invoke(Some_System.Delegate_Object, new object[] {item});
}
否则
someListBox.Items.Add(item);

我想要像...

if (someListBox.InvokeRequired)
{
someListBox.Invoke((i) => { someListBox.Items.Add(i); }, new object[] {item});
}
否则
someListBox.Items.Add(item);

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.

Is there a shortcut to this?

if (someListBox.InvokeRequired)
{
someListBox.Invoke(Some_System.Delegate_Object, new object[] {item});
}
else
someListBox.Items.Add(item);

I want something like...

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

待天淡蓝洁白时 2024-10-18 07:36:21

您的问题之一是编译器无法推断 lamda 的参数类型。即使对于给定的参数签名,也存在无限多个潜在的委托类型。所以你需要明确给出一个类型。如果您不关心参数名称,则 Action<...>Func<...> 是典型的候选者。

我认为这应该有效:

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

或者以重构的形式以避免重复:

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

而且我认为您根本没有理由希望将 i 作为参数:

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

One of your problems is that the compiler can't infer the parameter types of your 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.

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:

Action myAction = () => listviewResults.Items.Add(item);
if (someListBox.InvokeRequired)
{
    someListBox.Invoke( myAction );
}
else
    myAction();
怪我入戏太深 2024-10-18 07:36:21

您想要的方法的缺点是实际工作将在两个地方实施。一种替代方法可能如下所示:

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

话又说回来,您可以讨论此代码的执行频率。如果不是太多,也许最好通过不检查 InvokeRequired 来简化它,而是始终将调用包装在传递给 BeginInvoke 的委托中:

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

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:

private void AddItemToListView(ListViewItem item, ListView listView)
{
    listView.BeginInvoke((Action)delegate { listView.Items.Add(item); });       
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文