lambda expression and Messagebox in C#

5
private void SimpleLambda()
{
  dynamic showMessage =  x => MessageBox.Show(x);

  showMessage("Hello World!");
}

错误消息为: 无法将 lambda 表达式转换为动态类型,因为它不是委托类型。
需要帮助,

或者 Action<string> 或者 Func<string, DialogResult> - Mario S
一般来说,我建议您将 dynamic 视为一种高级功能,在正常代码中应避免使用。 - Brian
4个回答

16

这与MessageBox无关 - 就像错误消息所说的那样,您不能将Lambda表达式转换为dynamic,因为编译器不知道要创建哪种委托类型的实例。

您想要:

Action<string> action = x => MessageBox.Show(x);

甚至可以使用方法组转换,但这样你必须匹配返回类型:

Func<string, DialogResult> func = MessageBox.Show;

如果你想的话,你可以使用 dynamic

dynamic showMessage = action; // Or func
showMessage("Hello World!");

或者,您可以在显式委托实例表达式中指定lambda表达式:

dynamic showMessage = new Action<string>(x => MessageBox.Show(x));

1
@speti43 因为 Show 方法有一个返回类型。 - Mario S
@JonSkeet 那你就得到我的赞同了 =) - Mario S
@speti43:不完全是这样,因为变量的类型被编译器用来首先确定创建哪个委托实例。将委托实例分配给动态变量是可以的。 - Jon Skeet
3
你应该根据答案的实用性来投票,而不是根据答题者来投票。虽然这是一篇好的回答。 - Sayse
@Sayse: 当然这是个好答案,值得一票。"JON回答了它"只是另一个事实。干杯!! - Sangram Nandkhile
显示剩余3条评论

5
private void SimpleLambda()
{
  Action<string> showMessage =  x => MessageBox.Show(x);

  showMessage("Hello World!");
}

4

你需要声明委托类型,否则它不知道这个Lambda表达式应该是什么类型——x可以是任何东西。这应该可以解决问题:

Action<string> showMessage = x => MessageBox.Show(x);

请参考 Action<T> 以了解此委托类型的详细信息。

1
我为此创建了一个类型推断的辅助程序。如果我想将它们存储在临时变量中,我不喜欢手动输入lambda表达式的签名,所以我写成这样:
var fn = Func.F( (string x) => MessageBox.Show(x) );

或者

var fn = Func.F( (double x, double y) => x + y );

你仍需添加参数签名,但可以让类型推断处理返回类型。
实现如下:
using System;

namespace System
{
    /// <summary>
    /// Make type inference in C# work harder for you. Normally when
    /// you want to declare an inline function you have to type
    /// 
    ///     Func<double, double, double> fn = (a,b)=>a+b
    /// 
    /// which sux! With the below methods we can write
    /// 
    ///     var fn = Func.F((double a, double b)=>a+b);
    ///
    /// which is a little better. Not as good as F# type
    /// inference as you still have to declare the args
    /// of the function but not the return value which
    /// is sometimes not obvious straight up. Ideally
    /// C# would provide us with a keyword fun used like
    /// 
    ///     fun fn = (double a, double b)=>a+b;
    ///
    /// but till then this snippet will make it easier
    /// 
    /// </summary>
    public static class Func
    {
        public static Func<A> F<A>(Func<A> f)
        {
            return f; 
        }
        public static Func<A,B> F<A, B>(Func<A, B> f)
        {
            return f; 
        }
        public static Func<A,B,C> F<A, B,C>(Func<A, B,C> f)
        {
            return f; 
        }
        public static Func<A,B,C,D> F<A,B,C,D>(Func<A,B,C,D> f)
        {
            return f; 
        }
        public static Func<A,B,C,D,E> F<A,B,C,D,E>(Func<A,B,C,D,E> f)
        {
            return f; 
        }

        public static Action A(Action f)
        {
            return f; 
        }
        public static Action<_A> A<_A>(Action<_A> f)
        {
            return f; 
        }
        public static Action<_A,B> A<_A, B>(Action<_A, B> f)
        {
            return f; 
        }
        public static Action<_A,B,C> A<_A, B,C>(Action<_A, B,C> f)
        {
            return f; 
        }
        public static Action<_A,B,C,D> A<_A,B,C,D>(Action<_A,B,C,D> f)
        {
            return f; 
        }
        public static Action<_A,B,C,D,E> A<_A,B,C,D,E>(Action<_A,B,C,D,E> f)
        {
            return f; 
        }
    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接