C#将函数存储在Dictionary中

chi*_*chi 90 c# dictionary pointers function

如何创建一个可以存储函数的Dictionary?

谢谢.

我有大约30多个可以从用户执行的功能.我希望能够以这种方式执行该功能:

   private void functionName(arg1, arg2, arg3)
   {
       // code
   }

   dictionaryName.add("doSomething", functionName);

    private void interceptCommand(string command)
    {
        foreach ( var cmd in dictionaryName )
        {
            if ( cmd.Key.Equals(command) )
            {
                cmd.Value.Invoke();
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

但是,函数签名并不总是相同,因此具有不同数量的参数.

Dar*_*rov 109

像这样:

Dictionary<int, Func<string, bool>>
Run Code Online (Sandbox Code Playgroud)

这允许您存储带有字符串参数并返回布尔值的函数.

dico[5] = foo => foo == "Bar";
Run Code Online (Sandbox Code Playgroud)

或者如果函数不是匿名的:

dico[5] = Foo;
Run Code Online (Sandbox Code Playgroud)

Foo的定义如下:

public bool Foo(string bar)
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

更新:

看到您的更新后,您似乎事先并不知道要调用的函数的签名.在.NET中,为了调用一个函数,你需要传递所有的参数,如果你不知道参数是什么,实现这一点的唯一方法就是通过反射.

这是另一种选择:

class Program
{
    static void Main()
    {
        // store
        var dico = new Dictionary<int, Delegate>();
        dico[1] = new Func<int, int, int>(Func1);
        dico[2] = new Func<int, int, int, int>(Func2);

        // and later invoke
        var res = dico[1].DynamicInvoke(1, 2);
        Console.WriteLine(res);
        var res2 = dico[2].DynamicInvoke(1, 2, 3);
        Console.WriteLine(res2);
    }

    public static int Func1(int arg1, int arg2)
    {
        return arg1 + arg2;
    }

    public static int Func2(int arg1, int arg2, int arg3)
    {
        return arg1 + arg2 + arg3;
    }
}
Run Code Online (Sandbox Code Playgroud)

使用这种方法,您仍然需要知道需要在字典的相应索引处传递给每个函数的参数的数量和类型,否则您将收到运行时错误.如果您的函数没有返回值,请使用System.Action<>而不是System.Func<>.

  • 我不会贬低,但我只能说这种实施是一种反模式,没有**非常好的理由.如果OP期望客户端传递函数的所有参数,那么为什么首先要有一个函数表?为什么不让客户端简单地*调用*函数而没有动态调用的魔力? (3认同)
  • 如果我需要存储一个不带任何参数且没有返回值的函数怎么办? (2认同)

Jul*_*iet 8

但是,函数签名并不总是相同,因此具有不同数量的参数.

让我们从一些定义如下的函数开始:

private object Function1() { return null; }
private object Function2(object arg1) { return null; }
private object Function3(object arg1, object arg3) { return null; }
Run Code Online (Sandbox Code Playgroud)

你真的有两个可行的选择:

1)让客户直接调用您的功能,以保持类型安全.

这可能是最好的解决办法,除非你有非常从这个模型打破很好的理由.

当你谈到想要拦截函数调用时,听起来就像你正试图重新发明虚函数一样.有很多方法可以获得开箱即用的这种功能,例如从基类继承并覆盖其功能.

听起来像你想要一个更像包装的类而不是基类的派生实例,所以做这样的事情:

public interface IMyObject
{
    object Function1();
    object Function2(object arg1);
    object Function3(object arg1, object arg2);
}

class MyObject : IMyObject
{
    public object Function1() { return null; }
    public object Function2(object arg1) { return null; }
    public object Function3(object arg1, object arg2) { return null; }
}

class MyObjectInterceptor : IMyObject
{
    readonly IMyObject MyObject;

    public MyObjectInterceptor()
        : this(new MyObject())
    {
    }

    public MyObjectInterceptor(IMyObject myObject)
    {
        MyObject = myObject;
    }

    public object Function1()
    {
        Console.WriteLine("Intercepted Function1");
        return MyObject.Function1();
    }
    public object Function2(object arg1)
    {
        Console.WriteLine("Intercepted Function2");
        return MyObject.Function2(arg1);
    }

    public object Function3(object arg1, object arg2)
    {
        Console.WriteLine("Intercepted Function3");
        return MyObject.Function3(arg1, arg2);
    }
}
Run Code Online (Sandbox Code Playgroud)

2)OR将函数输入映射到公共接口.

如果您的所有功能都相关,这可能会有效.例如,如果您正在编写游戏,并且所有功能都会对玩家或玩家库存的某些部分执行某些操作.你最终得到这样的东西:

class Interceptor
{
    private object function1() { return null; }
    private object function2(object arg1) { return null; }
    private object function3(object arg1, object arg3) { return null; }

    Dictionary<string, Func<State, object>> functions;

    public Interceptor()
    {
        functions = new Dictionary<string, Func<State, object>>();
        functions.Add("function1", state => function1());
        functions.Add("function2", state => function2(state.arg1, state.arg2));
        functions.Add("function3", state => function3(state.arg1, state.are2, state.arg3));
    }

    public object Invoke(string key, object state)
    {
        Func<object, object> func = functions[key];
        return func(state);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 什么是"国家"? (2认同)

mod*_*e13 7

定义字典并将函数引用添加为值,使用System.Action类型:

using System.Collections;
using System.Collections.Generic;

public class Actions {

    public Dictionary<string, System.Action> myActions = new Dictionary<string, System.Action>();

    public Actions() {
        myActions ["myKey"] = TheFunction;
    }

    public void TheFunction() {
        // your logic here
    }
}
Run Code Online (Sandbox Code Playgroud)

然后用以下命令调用它:

Actions.myActions["myKey"]();
Run Code Online (Sandbox Code Playgroud)