【问题标题】:Is there a way to declare method that takes any lambda as parameter? [closed]有没有办法声明将任何 lambda 作为参数的方法? [关闭]
【发布时间】:2019-08-25 20:15:29
【问题描述】:

我正在尝试用 C# 编写一个可以接受任何类型的 lambda 的方法,但我不知道该怎么做。

我正在开发一个处理文本命令的类。我想以这样一种方式实现它,即参数将由处理特定命令的 lambda 表达式自动确定。

以下是我想要获取的 API 示例:

commandProcessor.AddCommand("setpos", (int x, int y)=>{
    //do stuff
});
commandProcessor.AddCommand("changename",(string newName)=>{
    //do completely different stuff
});

我的命令处理器将如下所示:

Dictionary<string, MagicType> mCommands;

public void AddCommand(string commandName, MagicType commandHandler){
    mCommands[commandName] = commandHandler;
}

是否有我可以使用的 MagicType,或者我应该使用完全不同的方法?

【问题讨论】:

    标签: c# .net reflection


    【解决方案1】:

    如果你真的需要这种功能,你可以这样做。

    public delegate object GenericCommand (params object[] parameters);
    

    然后,您需要为要存储的每个方法提供一个重载,该方法符合 GenericCommand 的定义。

    这是一个示例。

    using System;
    using System.Collections.Generic;
    
    public class Program
    {
        public delegate object GenericCommand (params object[] parameters);
    
        public static object Function1 (params object[] parameters) => Function1 ((int)parameters[0], (int)parameters[1]);
        public static int Function1 (int i, int j) => (i + j);
    
        private static Dictionary<string, GenericCommand> commands;
    
        public static void Main()
        {
            commands = new Dictionary<string, GenericCommand> ();
    
            commands.Add ("Function1", Function1);
    
            int i = (int)commands["Function1"](1, 2);
    
            Console.WriteLine (i); // 3
        }   
    }
    

    话虽如此,在 C# 这样的语言中执行此操作有些棘手是有原因的。在强类型语言中,期望在调用方法时,用户心中有一组特定的输入,并期望得到特定类型的输出。通常很少需要像GenericCommand 这样不起眼的东西,因为如果您知道该方法的名称以及它通常所在的位置,为什么不直接调用它呢?

    如果您发现自己在程序中非常需要这种功能,那么我会考虑用另一种语言编写基线的那部分。我对此的了解有限,但我相信F# 可以轻松完成您的要求。 Javascript 是另一种选择,但 F# 是作为 C# 的姊妹函数式语言编写的,因此它可能更容易集成到您的项目中。函数式语言(据我所知)更关心您正在编写的内容的纯功能,而不是操作数的性质,尽管我不太确定它是否与参数的数量一样不可知。这当然值得研究。

    【讨论】:

    • 最后我决定使用不同的方法。这个答案给了我一些有趣的思考。
    【解决方案2】:

    除了编译为Expressions 时,lambda 被编译为System.Delegate 的实例。但这是一种非常模糊的类型,您必须使用反射来发现任何东西。

    声明一组接受 ActionAction&lt;T&gt;Action&lt;T1, T2&gt; 等的重载可能会做得更好。这些是 BCL 的内置委托类型,用于返回 void 的函数。

    【讨论】:

    • “所有 lambdas 都是代表”——这不是真的。一个 lambda 是一个 lambda。根据上下文,它可以编译为委托实例化,或编译为表达式。后者不是代表。
    • @PeterDuniho 是的,我忘记了分配给 Expression 类型的 lambdas。会更新。
    猜你喜欢
    • 2017-01-16
    • 2011-12-20
    • 2012-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多