【问题标题】:Making Extension method Generic使扩展方法通用
【发布时间】:2010-06-12 14:35:57
【问题描述】:

在这个post 中,有一种非常有趣的方式可以使用静态扩展方法更新 UI 线程。

public static void InvokeIfRequired(this Control c, Action<Control> action)
{
    if(c.InvokeRequired)
    {
        c.Invoke(() => action(c));
    }
    else
    {
        action(c);
    }
}

我想做的是做一个通用的版本,所以我不受控件的限制。例如,这将允许我执行以下操作(因为我不再局限于成为一个控件)

this.progressBar1.InvokeIfRequired(pb => pb.Value = e.Progress);

我尝试了以下方法:

  public static void InvokeIfRequired<T>(this T c, Action<T> action) where T : Control
    {
        if (c.InvokeRequired)
        {
            c.Invoke(() => action(c));
        }
        else
        {
            action(c);
        }
    }

但我收到以下错误,我不确定如何修复。大家有什么建议吗?

错误 5 无法将 lambda 表达式转换为类型“System.Delegate”,因为它不是委托类型

【问题讨论】:

  • 事实上......看起来更近了一点,我似乎也得到了第一个代码示例的错误......虽然我现在实际上正在为 .NET 4.0 编译。

标签: c#-3.0


【解决方案1】:

替换:

c.Invoke(() => action(c));

与:

c.Invoke(action, c);

【讨论】:

    【解决方案2】:

    这是 lambda 和匿名方法的一个众所周知的错误:

    Convert this delegate to an anonymous method or lambda

    您的代码只需要转换即可编译:

    public static void InvokeIfRequired<T>(this T c, Action<T> action) where T : Control
    {
        if (c.InvokeRequired)
        {
            c.Invoke((Action<T>)((control) => action(control)));
        }
        else
        {
            action(c);
        }
    }
    

    【讨论】:

    • 也不行。您需要将操作的参数提供给Invoke 方法
    【解决方案3】:

    试试这个轻微的变化:

    public static void InvokeIfRequired<T>(this T c, Action<T> action) where T : Control
    {
        if (c.InvokeRequired)
        {
            c.Invoke((Action<T>)(() => action(c)));
        }
        else
        {
            action(c);
        }
    }
    

    您需要将其转换为委托类型。我知道有点愚蠢。我真的不能给你一个很好的理由,为什么不能将 lambda 表达式隐式分配为委托。

    【讨论】:

    • 这行不通,因为action 带了一个参数,而你没有将它传递给Invoke
    • 好点。编辑以说明这一点。出于某种原因,我认为 Invoke 在当前控件中传递,但事实并非如此。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-30
    • 1970-01-01
    • 2011-07-27
    • 1970-01-01
    • 1970-01-01
    • 2014-02-15
    • 1970-01-01
    相关资源
    最近更新 更多