2009-02-09 42 views
7

Làm thế nào để các đại biểu làm việc trong C# đằng sau hậu trường và làm thế nào họ có thể được sử dụng hiệu quả? EDIT: Tôi biết cách chúng hoạt động trên bề mặt (chúng về cơ bản là con trỏ hàm và cho phép các phương thức gọi lại với các chữ ký nhất định được gọi bằng cách sử dụng địa chỉ của chúng). Những gì tôi cần biết là CLR thực sự thực hiện chúng như thế nào trong nội bộ. Chính xác những gì xảy ra đằng sau hậu trường khi bạn xác định một đại biểu và khi bạn gọi một phương thức gọi lại bằng cách sử dụng đối tượng delegate?Cách đại biểu hoạt động (trong nền)?

Trả lời

4

Phần đầu tiên của câu hỏi là tương đối dễ dàng: đại biểu lưu trữ danh sách các con trỏ hàm. Nếu bạn gọi một đại biểu, nó sẽ gọi tất cả các con trỏ hàm trong danh sách nội bộ đó. Thêm và xóa người nhận (thông qua số Delegate.CombineDelegate.Remove) để thêm vào và xóa khỏi danh sách đó.

Để biết thêm thông tin cấp thấp, hãy tham khảo ECMA-335 (tiêu chuẩn CLI), phần II.14.5 (Con trỏ phương pháp) và II.14.6 (Đại biểu). Đặc biệt, lưu ý rằng một đại biểu bao gồm một con trỏ cá thể (loại System.Object) và một con trỏ phương thức (thuộc loại System.IntPtr). Một con trỏ phương pháp có thể thu được (trong CIL) thông qua các hướng dẫn ldftn hoặc ldvirtftn (cho các cuộc gọi chức năng ảo).

Hai thông tin này xác định bất kỳ phương pháp nào.

cách chúng có thể được sử dụng hiệu quả?

Ý bạn là gì? Bạn có biết về các sự kiện hoặc câu hỏi của bạn chuyên môn hơn không?

+0

Thật sao? Họ lưu trữ con trỏ? Tôi đã ấn tượng rằng các sự kiện đã làm điều đó, và các đại biểu giống như một loại hàm mạnh mẽ. (Nhưng tôi có thể là những điều khó hiểu ở đó.) – scraimer

+0

scraimer: Sự kiện sử dụng các đại biểu nội bộ. Thêm vào đó, họ cung cấp một giao diện để truy cập dễ dàng hơn. Tôi nên làm rõ điều này. –

+0

Tôi biết tất cả về các con trỏ hàm, nhưng điều tôi muốn biết là chúng thực sự được CLR triển khai như thế nào và cách tôi có thể khai thác kiến ​​thức về triển khai của chúng để sử dụng chúng hiệu quả hơn trong mã của tôi – Lonzo

5

Hiệu quả lại - không rõ ý bạn là gì, nhưng chúng có thể được sử dụng để đạt được hiệu suất, bằng cách tránh phản ánh tốn kém. Ví dụ: bằng cách sử dụng Delegate.CreateDelegate để tạo đại biểu được kiểm tra trước (đã nhập) thành phương pháp động/tra cứu, thay vì sử dụng (chậm) MethodInfo.Invoke.

Ví dụ nhỏ (truy cập mẫu tĩnh T Parse(string) cho loại), xem bên dưới. Lưu ý rằng nó chỉ sử dụng sự phản chiếu một lần (mỗi loại), thay vì nhiều lần. Điều này nên ngoài thực hiện một trong hai phản ánh hoặc điển hình TypeConverter sử dụng:

using System; 
using System.Reflection; 
static class Program { // formatted for space 
    static void Main() { 
     // do this in a loop to see benefit... 
     int i = Test<int>.Parse("123"); 
     float f = Test<float>.Parse("123.45"); 
    } 
} 
static class Test<T> { 
    public static T Parse(string text) { return parse(text); } 
    static readonly Func<string, T> parse; 
    static Test() { 
     try { 
      MethodInfo method = typeof(T).GetMethod("Parse", 
       BindingFlags.Public | BindingFlags.Static, 
       null, new Type[] { typeof(string) }, null); 
      parse = (Func<string, T>) Delegate.CreateDelegate(
       typeof(Func<string, T>), method); 
     } catch (Exception ex) { 
      string msg = ex.Message; 
      parse = delegate { throw new NotSupportedException(msg); }; 
     } 
    } 
} 
3

Các đại biểu trong C# là danh sách các gợi ý phương pháp. I E. chúng lưu trữ các tham chiếu đến mã và bạn có thể gọi các phương thức thông qua các con trỏ. Điều này rất hữu ích trong nhiều trường hợp. Ví dụ chung là dành cho trình xử lý sự kiện trong đó đại biểu được sử dụng để triển khai mẫu nhà xuất bản/người đăng ký.

1

Trình biên dịch C# tạo ra một lớp thổi đầy đủ khi bạn tạo một đại biểu. Lớp này chứa danh sách các tham chiếu hàm, như Konrad đã đề cập. Điều tốt đẹp về các đại biểu là họ cung cấp cho bạn cách dễ dàng để thực hiện tác vụ không đồng bộ với gọi lại thông báo. Điều này có nghĩa là bạn có thể được thông báo khi hoạt động nền của bạn hoàn thành. Threadpool không cung cấp tính năng này. Đại biểu là một chủ đề rộng lớn và tôi tìm thấy sách của Jeff Richter (CLR qua C#) và Albahari (C# 3) về sự giúp đỡ đặc biệt.

0

C# đại biểu là đối tượng (kiểm tra lớp System.Delegate) đóng gói tham chiếu đến đối tượng và con trỏ phương thức. Chúng cũng có thể có tham chiếu null đối tượng để biểu diễn cuộc gọi đến một phương thức tĩnh.

Khi gọi đại biểu bằng các đối số, đại biểu sẽ thực hiện cuộc gọi đến phương thức được tham chiếu trên đối tượng được tham chiếu với các đối số được chỉ định.

Một biên soạn phương pháp đại biểu Invoke được xử lý trực tiếp bởi bộ thực thi (như có thể nhìn thấy với Reflector):

[MethodImpl(0, MethodCodeType=MethodCodeType.Runtime)] 
public virtual void Invoke(T obj); 

Thời gian chạy sử dụng tất cả các thông tin internaly để biên dịch một cuộc gọi phương pháp tiêu chuẩn cho phương thức được tham chiếu.

4

Khi bạn định nghĩa đại biểu của bạn

internal delegate void Feedback(Int32 value); 

trình biên dịch thực sự định nghĩa một lớp hoàn toàn trông giống như thế này:

internal class Feedback : System.MulticastDelegate { 
    // Constructor 
    public Feedback(Object object, IntPtr method); 

    // Method with same prototype as specified by the source code 
    public virtual void Invoke(Int32 value); 

    // Methods allowing the callback to be called asynchronously 
    public virtual IAsyncResult BeginInvoke(Int32 value, AsyncCallback callback, Object object); 

    public virtual void EndInvoke(IAsyncResult result); 
} 

Nguồn: Jeffrey Richter - CLR via C#, chương 17

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