2009-03-04 29 views

Trả lời

7

A Delegatetype không thể khai báo trong giao diện. Bạn có thể muốn sử dụng một sự kiện (nếu thích hợp) hoặc khai báo một đại biểu bên ngoài giao diện nhưng trong cùng một không gian tên.

Liên kết này có thể Help- When to Use Delegates Instead of Interfaces

23

một đại biểu chỉ là một loại, do đó bạn không đạt được bất cứ điều gì bằng cách đặt nó bên trong giao diện.

Bạn không cần tạo đại biểu của riêng mình. Hầu hết thời gian bạn chỉ nên sử dụng EventHandler, Func, Predicate hoặc Action.

Tôi có thể hỏi đại biểu của bạn trông như thế nào không?

+2

1 Tôi không hiểu tại sao một người nào đó Đặt cho bạn một phiếu bầu ... – eglasius

+2

Câu trả lời này thực sự cũng giải quyết được vấn đề của tôi mà tôi không bao giờ có thể tìm được cách tốt để sử dụng các đại biểu trong các tình huống mà tôi muốn sử dụng chúng. I E. không sử dụng 'm :). –

31

Bạn có thể sử dụng bất kỳ trong số này:

public delegate double CustomerDelegate(int test); 
public interface ITest 
{ 
    EventHandler<EventArgs> MyHandler{get;set;} 
    CustomerDelegate HandlerWithCustomDelegate { get; set; } 
    event EventHandler<EventArgs> MyEvent; 
} 
+5

Tại sao tạo CustomerDelegate khi bạn chỉ có thể sử dụng Func ? –

+1

Tôi biết, tôi chỉ minh họa rằng bạn có thể sử dụng khá nhiều thứ :) – eglasius

+8

Rất khó hiểu các thông số như Func . Có ý nghĩa hơn nhiều khi có tên cho chữ ký đó. – diachedelic

4

Các tài liệu nói rõ rằng bạn có thể xác định một đại biểu trong một giao diện:

Một giao diện chỉ chứa các chữ ký của phương pháp, các đại biểu hoặc sự kiện.

MSDN: interface (C# Reference)

Tuy nhiên, trong bài phát biểu trên cùng một trang nó nói rằng một giao diện có thể chứa các chữ ký của phương pháp, tài sản, indexers và sự kiện.

Nếu bạn cố gắng để đặt một đại biểu trong một giao diện, trình biên dịch nói rằng "giao diện không thể khai báo các loại."

Tiêu chuẩn Ecma-334 (8.9 Giao diện) đồng ý với các nhận xét trên trang đó và trình biên dịch.

+2

Dường như lỗi trong MSDN. Đó phải là "chữ ký của phương pháp, tài sản hoặc sự kiện", phải không? – configurator

6

đây là một decalaration đại biểu TYPE ...

public delegate returntype MyDelegateType (params) 

này không thể được khai báo trong một giao diện vì nó là một tuyên bố loại

tuy nhiên sử dụng cách khai báo kiểu trên bạn có thể sử dụng một thể hiện ủy nhiệm

MyDelegateType MyDelegateInstance (get; set;) 

vì vậy các phiên bản ủy quyền là OK nhưng khai báo loại ủy quyền không (trong giao diện)

+0

Câu trả lời hay nhất cho đến nay. Đến điểm. Tôi rất thích khi mọi người đi đến điểm thay vì viết bài phát biểu. – DavidGuaita

1

Như những người khác đã đề cập, bạn chỉ có thể xác định các đại biểu bên ngoài của giao diện.

Có rất ít hoặc không có gì sai với các đại biểu. Cá nhân tôi nghĩ rằng Func<int, double> là kém hấp dẫn hơn so với sử dụng các đại biểu:

  1. Bạn không thể đặt tên các đối số, vì vậy ý ​​nghĩa lý luận có thể mơ hồ
  2. Đó là tin tức cũ mà sự kiện được không đề an toàn, do đó sau mã không lý tưởng:

    if (MyFuncEvent != null) 
    { 
        MyFuncEvent(42, 42.42); 
    } 
    

    Xem: http://kristofverbiest.blogspot.com/2006/08/better-way-to-raise-events.html

    mã an toàn hơn là:

    MyFuncEventHandler handler = MyFuncEvent; 
    if (handler != null) 
    { 
        handler(42, 42.42); 
    } 
    
  3. Bạn cần phải lặp lại trong các chữ ký của sự kiện nếu bạn muốn lưu nó vào một biến (hoặc bạn có thể sử dụng var, mà tôi không thích). Nếu bạn có nhiều lý lẽ thì điều này có thể rất tẻ nhạt (một lần nữa, bạn luôn có thể lười biếng và sử dụng var).

    Func<int, double, string, object, short, string, object> handler = MyFuncEvent; 
    if (handler != null) 
    { 
        handler(42, 42.42, ...); 
    } 
    

đại biểu giúp bạn tiết kiệm từ phải lặp lại chữ ký của phương pháp/sự kiện mỗi khi bạn muốn gán nó vào một kiểu biến.

+0

Tuy nhiên, lưu ý rằng bạn _can_ đặt tên đối số tại trang gọi của hàm lambda (nhưng chỉ khi có nhiều hơn hai): Hành động f = (int i, int j) => {}; /* giống như, */ var g = (Hành động ) ((i, j) => {}); Thật kỳ lạ, bạn không thể sử dụng 'var' khi sử dụng cú pháp cũ (đây là khi cần ít nhất). –

+0

Thật tuyệt khi biết! – swooby

0

Phương thức giao diện có thể chấp nhận đại biểu làm thông số, không có vấn đề gì. (Có lẽ tôi không thấy vấn đề?) Nhưng nếu ý định là chỉ định một cuộc gọi đi trong giao diện, hãy sử dụng một sự kiện.

Có quá nhiều chi tiết nhỏ, dễ dàng hơn nhiều khi chỉ hiển thị một số mã thay vì cố gắng mô tả tất cả trong văn xuôi. (Xin lỗi, ngay cả những mẫu mã là một chút cồng kềnh ...)

namespace DelegatesAndEvents 
{ 
    public class MyEventArgs : EventArgs 
    { 
     public string Message { get; set; } 
     public MyEventArgs(string message) { Message = message; } 
    } 

    delegate void TwoWayCallback(string message); 
    delegate void TwoWayEventHandler(object sender, MyEventArgs eventArgs); 

    interface ITwoWay 
    { 
     void CallThis(TwoWayCallback callback); 

     void Trigger(string message); 
     event TwoWayEventHandler TwoWayEvent; 
    } 

    class Talkative : ITwoWay 
    { 
     public void CallThis(TwoWayCallback callback) 
     { 
      callback("Delegate invoked."); 
     } 

     public void Trigger(string message) 
     { 
      TwoWayEvent.Invoke(this, new MyEventArgs(message)); 
     } 

     public event TwoWayEventHandler TwoWayEvent; 
    } 

    class Program 
    { 
     public static void MyCallback(string message) 
     { 
      Console.WriteLine(message); 
     } 

     public static void OnMyEvent(object sender, MyEventArgs eventArgs) 
     { 
      Console.WriteLine(eventArgs.Message); 
     } 

     static void Main(string[] args) 
     { 
      Talkative talkative = new Talkative(); 

      talkative.CallThis(MyCallback); 

      talkative.TwoWayEvent += new TwoWayEventHandler(OnMyEvent); 
      talkative.Trigger("Event fired with this message."); 

      Console.ReadKey(); 
     } 
    } 
} 
Các vấn đề liên quan