2011-08-12 30 views
7

Böyle büyük bir switch ifadesi ile bu yöntemi vardır: Statik Sözlük

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) {...} 

Şimdi ben switch deyimi ortadan kaldırabilir böylece Func<> delege sözlükle bu değiştirerek düşündü:

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

bununla bakın sorun, yeni bir sözlük örneği ve Sınıfım her yeni örneği doldurulur olmasıdır.

Sözlük'ü (örnek yöntemlere temsilci içeren) statik yapıcıda yalnızca bir kez başlatılacak statik bir üye yapmak bir şekilde mümkün müdür?

E.g. böyle bir şey (çalışmıyor):

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

Neden çalışmıyor, hata nedir? Belki de statik bir alıcıda tembelleşirseniz, işe yarıyor mu? Ben genellikle böyle, singleton, vb için gidiyorum. – ewernli

+0

@ewernli: soruyu derleyici hatasıyla güncelledi. (Not: Statik yöntemler yerine örnek yöntemlerini çağırmam gerekir). – M4N

+0

Aldığınız hata, sözlüğünüzde 'MyClass.Method1' ifadesini' Func 'olarak eklemeyi denemektir. Sözlüğün kendisinin statik kurulumu değil. 'Method1' yöntemi' MyClass' kapalı statik bir yöntem midir? Aldığınız hata, olmadığını ve derleyicinin olmasını beklediğini gösterir. – Clayton

cevap

18

Sen statik yapıcı bunu başlatabilir - ama seni varsayalım, çünkü ne istediğinizi olmayabilir MyClass örneklerini oluşturmak gerekir Komutun, Execute'un çağrıldığı örneği "bağlamında" yürütmesini isteyin.

Alternatif olarak, bu gibi MyClass örneğidir yanı almak delegelerle sözlüğü doldurabilirsiniz: Teoride

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 == ""; 
    } 
} 

Ben lambda ifadesi olmadan yapılabilir olması gerektiğine inanıyoruz bir oluşturarak " Açık delege ", ancak yansıma kullanarak biraz daha fazla çalışmaya gerek duyardı. Eğer çirkinlik ve küçük performansının fazla indirilmesi cezasını aldırmıyorsanız, bu yaklaşımın gayet iyi çalışması gerektiğini düşünüyorum.

+0

Evet, komutun Execute() çağrıldığı aynı örnek üzerinde yürütülmesini istiyorum - böylece alternatif çözümünüz İhtiyacım olan şey gibi görünüyor. Teşekkürler. – M4N

+0

Bu eski bir iş parçacığıdır ancak statik sözlüğün çöp toplamadaki delegelerle etkisini bilmek istiyorum. Benim tahminim statik sözlük olduğu için, sonunda 2 nesline terfi ettirilecek ve sadece orada kalarak çöp toplayamayacak. Düşünceleriniz lütfen Jon – AlwaysAProgrammer

+0

@AlwaysAProgrammer: Delegelerin neden bu kadar alakalı olduklarını anlamıyorum. Evet, delegeler sonsuza kadar var olacak ...ama buradaki niyet bu ... –