2009-03-02 52 views
20

Tôi muốn tạo ra một tổng quát để mà tôi có thể vượt qua một chức năng như một tham số, tuy nhiên chức năng này có thể bao gồm các thông số bản thân như vậy ...Chuyển một hàm (có tham số) làm tham số?

int foo = GetCachedValue("LastFoo", methodToGetFoo) 

như vậy mà:

protected int methodToGetFoo(DateTime today) 
{ return 2; // example only } 

Về cơ bản tôi muốn để có một phương thức sẽ kiểm tra bộ nhớ cache cho một giá trị, nếu không sẽ tạo ra giá trị dựa trên phương thức được truyền vào.

Suy nghĩ?

+0

Tôi không biết làm thế nào để làm điều này, nhưng như một lưu ý, câu hỏi này dường như không liên quan gì đến generics như tôi có thể nói. – recursive

+0

Đó là loại, một chút, có thể. Có lẽ "đại biểu" nên thay thế "generics". – mquander

+0

Xin lỗi, tôi đã tạo một phương pháp chung để xử lý việc này, vì vậy tôi đã giả định rằng nó có liên quan. Nhưng việc đi qua thực sự là đại biểu có liên quan, vì vậy tôi sẽ cập nhật. Cảm ơn – klkitchens

Trả lời

37

Có vẻ như bạn muốn có một Func<T>:

T GetCachedValue<T>(string key, Func<T> method) { 
    T value; 
    if(!cache.TryGetValue(key, out value)) { 
     value = method(); 
     cache[key] = value; 
    } 
    return value; 
} 

Người gọi sau đó có thể quấn này bằng nhiều cách; cho các chức năng đơn giản:

int i = GetCachedValue("Foo", GetNextValue); 
... 
int GetNextValue() {...} 

hoặc trong trường hợp tranh cãi có liên quan, đóng cửa:

var bar = ... 
int i = GetCachedValue("Foo",() => GetNextValue(bar)); 
+1

Cảm ơn tôi đã rất gần, nhưng không thể tìm cách để có được parms ngay trong chung chung.Lựa chọn cuối cùng, với việc đóng cửa là chìa khóa! Làm việc như một say mê. – klkitchens

+2

Thực sự cũ ở đây nhưng phần đóng cửa chỉ là những gì tôi đang tìm kiếm –

4

Bạn có thể tạo đại biểu của riêng bạn, nhưng trong C# 3.0 bạn có thể tìm thấy nó thuận tiện hơn để sử dụng được xây dựng trong Func<T> gia đình đại biểu để giải quyết vấn đề này. Ví dụ:

public int GetCachedValue(string p1, int p2, 
          Func<DateTime, int> getCachedValue) 
{ 
    // do some stuff in here 
    // you can call getCachedValue like any normal function from within here 
} 

Phương thức này sẽ lấy ba đối số: một chuỗi, một hàm int và hàm lấy DateTime và trả về một int. Ví dụ:

int foo = GetCachedValue("blah", 5, methodToGetFoo); // using your method 
int bar = GetCachedValue("fuzz", 1, d => d.TotalDays); // using a lambda 

Khác nhau Func<T, U, V...> vv loại tồn tại trong khuôn khổ để chứa các phương pháp với số lượng đối số khác nhau.

3

Tạo một đại biểu cho phương pháp methodToGetFoo

public delegate object GenerateValue(params p); 
public event GenerateValue OnGenerateValue; 

Xác định GetCachedValue sử dụng các đại biểu

int GetCachedValue(string key, GenerateValue functionToCall); 

Sau đó, trong việc thực hiện OnGenerateValue bạn có thể kiểm tra của param.

2

Here là một cái gì đó đơn giản tôi bắt đầu có thể được thực hiện thêm một chút (như tôi đã làm cho một dự án thương mại).

Trong trường hợp của tôi này là bộ nhớ cache cuộc gọi dịch vụ web, và được sử dụng một cái gì đó như:

WebService ws = new WebService(); 
var result = ws.Call(x => x.Foo("bar", 1)); // x is the ws instance 
7

Sử dụng System.Action và biểu thức lambda (phương pháp anonimous). Ví dụ:

public void myMethod(int integer){ 

    //Do something 

} 

public void passFunction(System.Action methodWithParameters){ 

    //Invoke 
    methodWithParameters(); 

} 

//... 

//Pass anonimous method using lambda expression 
passFunction(() => myMethod(1234)); 
Các vấn đề liên quan