包含实例方法委托的静态字典

发布于 2024-11-28 23:51:48 字数 1215 浏览 0 评论 0原文

我有一个带有巨大 switch 语句的方法,如下所示:

public bool ExecuteCommand(string command, string args)
{
    bool result = false;
    switch (command)
    {
        case "command1": result = Method1(args); break;
        case "command2": result = Method2(args); break;
        // etc.
    }
    return result;
}
private bool Method1(string args) {...}

现在我考虑用 Func<> 委托字典替换它,以便我可以消除 switch 语句:

private Dictionary<string, Func<string, bool>> _commands = new ...;
public MyClass()
{
    _commands.Add("command1", Method1);
    // etc:
}
public bool ExecuteCommand(string command, string args)
{
    return _commands[command](args);
}

我看到的问题是,是用 MyClass 的每个新实例实例化并填充一个新字典。

是否有可能以某种方式使该字典(包含实例方法的委托)成为静态成员,在静态构造函数中仅初始化一次?

例如这样的东西(不起作用):

private static Dictionary<string, Func<string, bool>> _commands = new ...;
static MyClass()
{
    // the following line will result in a compiler error:
    // error CS0120: An object reference is required for the non-static field,
    // method, or property 'MyClass.Method1(string, string)'
    _commands.Add("command1", MyClass.Method1);
}

I have this method with a huge switch statement like this:

public bool ExecuteCommand(string command, string args)
{
    bool result = false;
    switch (command)
    {
        case "command1": result = Method1(args); break;
        case "command2": result = Method2(args); break;
        // etc.
    }
    return result;
}
private bool Method1(string args) {...}

Now I thought about replacing this with a dictionary of Func<> delegates so that I can eliminate the switch statement:

private Dictionary<string, Func<string, bool>> _commands = new ...;
public MyClass()
{
    _commands.Add("command1", Method1);
    // etc:
}
public bool ExecuteCommand(string command, string args)
{
    return _commands[command](args);
}

The problem I see with this, is that a new Dictionary is instantiated and populated with each new instance of MyClass.

Is it possible to somehow make that Dictionary (containing delegates to instance methods) a static member, which would be initialized only once, in the static constructor?

E.g. something like this (does not work):

private static Dictionary<string, Func<string, bool>> _commands = new ...;
static MyClass()
{
    // the following line will result in a compiler error:
    // error CS0120: An object reference is required for the non-static field,
    // method, or property 'MyClass.Method1(string, string)'
    _commands.Add("command1", MyClass.Method1);
}

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

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

发布评论

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

评论(1

假装爱人 2024-12-05 23:51:48

可以在静态构造函数中初始化它 - 但您需要创建MyClass的实例,这可能不是您想要的,因为我假设您希望命令在已调用 Execute 的实例的“上下文中”执行。

或者,您也可以使用委托来填充字典,这些委托也获取MyClass的实例,如下所示:

class MyClass
{
    static Dictionary<string, Func<MyClass, string, bool>> commands
        = new Dictionary<string, Func<MyClass, string, bool>>
    {
        { "Foo", (@this, x) => @this.Foo(x) },
        { "Bar", (@this, y) => @this.Bar(y) }
    };

    public bool Execute(string command, string value)
    {
        return commands[command](this, value);
    }

    public bool Foo(string x)
    {
        return x.Length > 3;
    }

    public bool Bar(string x)
    {
        return x == "";
    }
}

理论上,我相信通过创建一个“开放委托”,但使用反射需要做更多的工作。如果您不介意额外间接带来的丑陋和微小性能损失,我认为这种方法应该效果很好。

You can initialize it in the static constructor - but you'll need to create instances of MyClass, which may not be what you want, because I assume you want the command to execute "in the context of" the instance which Execute has been called on.

Alternatively, you can populate the dictionary with delegates which take an instance of MyClass as well, like this:

class MyClass
{
    static Dictionary<string, Func<MyClass, string, bool>> commands
        = new Dictionary<string, Func<MyClass, string, bool>>
    {
        { "Foo", (@this, x) => @this.Foo(x) },
        { "Bar", (@this, y) => @this.Bar(y) }
    };

    public bool Execute(string command, string value)
    {
        return commands[command](this, value);
    }

    public bool Foo(string x)
    {
        return x.Length > 3;
    }

    public bool Bar(string x)
    {
        return x == "";
    }
}

In theory I believe it should be doable without the lambda expression by creating an "open delegate", but it would need a bit more work using reflection. If you don't mind the ugliness and tiny performance penalty of the extra indirection, I think this approach should work quite well.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文