2011-06-20 40 views
6

Tôi cần biết thêm một chút về các đại biểu và thiết kế ngôn ngữ C#.Làm thế nào để có được danh sách kết quả của lời kêu gọi của đại biểu?

Hãy nói, tôi có một MulticastDelegate mà thực hiện generic đại biểu và chứa một số cuộc gọi:

Func<int> func = null; 
func += ()=> return 8; 
func +=() => return 16; 
func +=() => return 32; 

Bây giờ mã này sẽ trở lại 32:

int x = func(); // x=32 

Tôi muốn biết nếu có tồn tại (hoặc tốt hơn tôi nên hỏi tại sao nó không tồn tại!) Tính năng ngôn ngữ C# sử dụng có thể nhận được quyền truy cập vào kết quả của tất cả các cuộc gọi của đại biểu, điều đó có nghĩa là lấy danh sách ({8,16,32})?

Tất nhiên, có thể thực hiện tương tự bằng cách sử dụng các thường trình khuôn khổ .NET. Một cái gì đó như thế này sẽ làm việc:

public static List<TOut> InvokeToList<TOut>(this Func<TOut> func) 
{ 
    var returnValue = new List<TOut>(); 
    if (func != null) 
    { 
     var invocations = func.GetInvocationList(); 
     returnValue.AddRange(invocations.Select(@delegate => ((Func<TOut>) @delegate)())); 
    } 
    return returnValue; 
} 

Nhưng tôi không thể thoát ra khỏi hệ thống mà cần có những cách tốt hơn, ít nhất là không đúc (thực sự, tại sao MulticastDelegate là không chung khi các đại biểu là)?

+2

'thực sự, tại sao MulticastDelegate không nằm trong khuôn khổ kể từ 1.1, có nghĩa là khi nó được mã hóa không có sẵn bất kỳ generics nào. – Will

Trả lời

2

Bạn có thể thực hiện những gì bạn muốn nếu bạn không sử dụng Func<int>, nhưng một Hành động lấy một phương thức làm tham số xử lý giá trị trả lại. Dưới đây là một ví dụ nhỏ:

static Action<Action<int>> OnMyEvent=null; 

    static void Main(string[] args) 
    { 
     OnMyEvent += processResult => processResult(8); 
     OnMyEvent += processResult => processResult(16); 
     OnMyEvent += processResult => processResult(32); 

     var results = new List<int>(); 
     OnMyEvent(val => results.Add(val)); 

     foreach (var v in results) 
      Console.WriteLine(v); 

    } 
+0

Bây giờ tôi có được những gì tôi muốn với các đại biểu của Listof (để thoát khỏi mọi thứ với "GetInvocations"), nhưng mẫu của bạn cho tôi thêm ý tưởng. Cảm ơn bạn. Cách suy nghĩ tốt đẹp. –

6

Không, không có cách nào tốt hơn - khi bạn gọi đại biểu đa hướng, kết quả chỉ là kết quả của đại biểu cuối cùng. Đó là những gì nó giống như ở cấp khung.

Đại biểu đa phương tiện là chủ yếu là hữu ích cho trình xử lý sự kiện. Khá hiếm khi sử dụng chúng cho các chức năng như thế này.

Lưu ý rằng Delegate cũng không phải là chung chung - chỉ riêng lẻ loại đại biểu có thể là chung chung, vì tính chất của loại có thể thay đổi dựa trên loại. (ví dụ: Action<T>Action<T1, T2> là các loại không liên quan thực sự.)

+0

MulticastDelegate là trừu tượng vì vậy tôi phải hiểu rằng đại biểu cụ thể như hành động "một nơi nào đó bên trong" sản xuất thừa kế lớp (con của MulticastDelegate)? Sau đó, tại sao không thể thêm phương thức GetTypedInvocations mới để trả về chứ không phải Delegate [] nhưng Action []? –

+0

@Roman: Có, mỗi loại cụ thể có thể thêm phương pháp riêng của loại đó - mặc dù nó sẽ cần tạo mảng liên quan, v.v. –

1

Không có cách nào để có được) ngoại lệ b) giá trị trả về từ đại biểu, chỉ bằng cách đánh hơi vào danh sách kết quả. Một cách khác là chỉ có danh sách các đại biểu và quản lý nó theo cách thủ công.

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