2011-08-12 64 views
7

我有這樣的方法,像這樣一個巨大的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<>代表字典更換,這樣我可以消除開關語句:

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實例。

是否有可能在靜態構造函數中以某種方式使該Dictionary(包含委託給實例方法)成爲靜態成員,該靜態成員將被初始化一次?

例如這樣的事情(不工作):

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); 
} 
+2

爲什麼它不起作用,錯誤是什麼?也許如果你懶惰初始化在一個靜態的getter,它的工作原理?這就是我通常的做法,對於單身人士等。 – ewernli

+0

@ewernli:用編譯器錯誤更新了問題。 (注意:我需要調用實例方法,而不是靜態方法)。 – M4N

+0

您收到的錯誤是引用嘗試在您的字典中添加'MyClass.Method1'作爲'Func '。不是Dictionary本身的靜態設置。 'Method1'方法關閉'MyClass'是一種靜態方法嗎?您收到的錯誤表明它不是,編譯器期望它。 – Clayton

回答

18

在靜態構造函數可以初始化它 - 但你需要創建的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 == ""; 
    } 
} 

從理論上講,我相信它應該是可行的,而不lambda表達式通過創建「打開委託「,但它需要使用反射更多的工作。如果你不介意醜陋和額外間接的性能損失,我認爲這種方法應該工作得很好。

+0

是的,我希望命令在調用Execute()的同一個實例上執行 - 所以你的替代解決方案似乎是我需要的。謝謝。 – M4N

+0

這是一箇舊的線程,但我想知道靜態字典與委託對垃圾回收的影響。我的猜測是,因爲它是靜態字典,它最終會被提升到第二代,並且可能會停留在那裏,而不會被垃圾收集。你的想法請Jon – AlwaysAProgrammer

+0

@AlwaysAProgrammer:我不明白爲什麼代表與此特別相關。是的,代表將永遠存在...但這是這種情況下的意圖...... –