2011-08-12 27 views
7

tôi có phương pháp này với một câu lệnh switch khổng lồ như thế này:từ điển tĩnh chứa các đại biểu với các phương pháp dụ

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

Bây giờ tôi nghĩ đến việc thay thế này với một cuốn từ điển của Func<> đại biểu để tôi có thể loại bỏ các câu lệnh 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); 
} 

Vấn đề tôi thấy với điều này, là một từ điển mới được khởi tạo và phổ biến với mỗi phiên bản mới của MyClass.

Có thể bằng cách nào đó làm cho từ điển đó (có chứa các đại biểu cho các phương thức mẫu) một thành viên tĩnh, chỉ được khởi tạo một lần, trong hàm dựng tĩnh không?

Ví dụ: một cái gì đó như thế này (không hoạt động):

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

Tại sao nó không hoạt động, lỗi là gì? Có lẽ nếu bạn lười biếng-khởi tạo trong một getter tĩnh, nó hoạt động? Đó là cách tôi thường xuyên sử dụng, đối với singleton, v.v. – ewernli

+0

@ewernli: cập nhật câu hỏi với lỗi trình biên dịch. (lưu ý: Tôi cần gọi phương thức instance, không phải phương thức tĩnh). – M4N

+0

Lỗi mà bạn đang nhận đang tham chiếu đến việc thêm 'MyClass.Method1' làm chuỗi' Func <, bool> 'trong từ điển của bạn. Không phải thiết lập tĩnh của chính Từ điển. Phương thức 'Method1' có tắt' MyClass' là phương thức tĩnh không? Lỗi bạn nhận được cho biết nó không phải và trình biên dịch mong đợi nó được. – Clayton

Trả lời

18

Bạn thể khởi tạo nó trong constructor tĩnh - nhưng bạn sẽ cần phải tạo ra các trường hợp MyClass, mà có thể không được những gì bạn muốn, bởi vì tôi giả sử bạn muốn lệnh để thực hiện "trong ngữ cảnh của" trường hợp mà Execute đã được gọi.

Ngoài ra, bạn có thể di chuyển từ điển với các đại biểu mà mất một thể hiện của MyClass là tốt, như thế này:

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

Về lý thuyết Tôi tin rằng nó nên được doable mà không có biểu thức lambda bằng cách tạo ra một " mở đại biểu ", nhưng nó sẽ cần một chút công việc hơn bằng cách sử dụng sự phản chiếu. Nếu bạn không nhớ xấu xí và nhỏ hình phạt về hiệu suất của sự gián đoạn thêm, tôi nghĩ cách tiếp cận này sẽ hoạt động khá tốt.

+0

Vâng, tôi muốn lệnh được thực thi trên cùng một thể hiện mà Execute() được gọi - vì vậy giải pháp thay thế của bạn có vẻ là những gì tôi cần. Cảm ơn. – M4N

+0

Đây là một chủ đề cũ nhưng tôi muốn biết tác động của từ điển tĩnh với các đại biểu trên Bộ sưu tập rác. Tôi đoán là vì nó là từ điển tĩnh, nó cuối cùng sẽ được thăng lên thế hệ 2 và có thể chỉ ở đó và không thu gom rác. Suy nghĩ của bạn xin vui lòng Jon – AlwaysAProgrammer

+0

@AlwaysAProgrammer: Tôi không thấy lý do tại sao các đại biểu đặc biệt liên quan đến điều đó. Có, các đại biểu sẽ tồn tại mãi mãi ...nhưng đó là ý định trong trường hợp này ... –

Các vấn đề liên quan