2009-06-30 19 views
6

Tôi cần viết hàm đại biểu có thể 'quấn' một số trong khi/try/catch code xung quanh cuộc gọi UDP cơ bản để xác minh liên kết. Tôi đã làm cho nó làm việc cho Func cho một chức năng mà không có đối số, nhưng tôi không thể làm cho nó làm việc cho hành động, trong đó có một đối số (nhưng không trở lại). Tôi dường như không thể vượt qua trong các đối số một cách hợp lý mà không có trình biên dịch phàn nàn.Sử dụng Action <T> làm đối số trong C# (bắt chước một con trỏ hàm)

Tôi có hoàn toàn sai về điều này không? Tôi mới đến C# và tôi chủ yếu cố gắng bắt chước ý tưởng của một con trỏ hàm. Tôi có nên không quá tải chức năng này không? Tôi biết bạn không thể quá tải đại biểu (tôi giả định đó là lý do tại sao Func và hành động tồn tại).

này hoạt động:

protected TResult udpCommand<TResult>(Func<TResult> command) 
     { 
      TResult retValue = default(TResult); 
      while (!linkDownFail) 
      { 
       try 
       { 
        retValue = command(); 
        break; 
       } 
       catch 
       { 
        LinkStateCallBack(ip, getLinkStatus()); 
        if (linkDownFail) throw new LinkDownException(); 
        Thread.Sleep(100); 
       } 
      } 
      return retValue; 
     } 

Nhưng điều này không:

protected void udpCommand<T>(Action<T> command(T value)) 
     { 
      while(!linkDownFail) 
      { 
       try 
       { 
        command(value); 
        break; 
       } 
       catch 
       { 
        LinkStateCallBack(ip, getLinkStatus()); 
        if (linkDownFail) throw new LinkDownException(); 
        Thread.Sleep(100); 
       } 
      } 
      return; 
     } 

Calling ước (đối với một trong những hoạt động):

udpCommand<uint>(someUdpCommand); 
+2

Bổ sung - bạn không thực sự cần T; bạn chỉ có thể thực hiện 'Action' (no arg), và gọi là: udpCommand (() => SomeMethod (123)); –

+0

Điều này có cho phép tôi có một số thông số đầu vào khác nhau để udpCommand mà không làm quá tải thông số cho tối đa 4 tham số không? Đó là những gì tôi cần làm. Tôi vẫn cần một Func và một hành động? – cgyDeveloper

Trả lời

10

Nếu bạn muốn điều này phải đủ tổng quát để xử lý bất kỳ số lượng các đối số , hãy thử sử dụng đại diện Tác vụ không thuộc về hành động:

protected void udpCommand(Action command) 
{ 
    while(!linkDownFail) 
    { 
     try 
     { 
      command(); 
      break; 
     } 
     catch 
     { 
      LinkStateCallBack(ip, getLinkStatus()); 
      if (linkDownFail) throw new LinkDownException(); 
      Thread.Sleep(100); 
     } 
    } 
    return; 
} 

Trong C# 3.0, bạn có thể gọi nó như sau:

udpCommand(() => noParameterMethod()); 
udpCommand(() => singleParameterMethod(value)); 
udpCommand(() => manyParameterMethod(value, value2, value3, value4)); 

Trong C# 2.0 đó là một xấu xí chút:

udpCommand(delegate { noParameterMethod(); }); 
udpCommand(delegate { singleParameterMethod(value); }); 
udpCommand(delegate { manyParameterMethod(value, value2, value3, value4); }); 

này cho phép bạn thực hiện chậm mà không cần khóa bạn vào chữ ký phương pháp cụ thể.

EDIT

Tôi chỉ nhận thấy tôi kinda lấy trộm bình luận Marc Gravell của ... xin lỗi Marc. Để trả lời làm thế nào bạn có thể làm giảm sự trùng lặp của bạn, bạn có thể có phương pháp Action gọi Func<T> phương pháp, như thế này:

protected void udpCommand(Action command) 
{ 
    udpCommand(() => { command(); return 0; }); 
} 

Tôi tin rằng (và tôi có thể sai) mà trở về 0 là không tốn kém hơn (ngầm) trở về void, nhưng tôi có thể là cách tắt ở đây.Ngay cả khi nó có một chi phí, nó sẽ chỉ đặt một snoodge bitty nhỏ xíu thêm vào ngăn xếp. Trong hầu hết các trường hợp, chi phí bổ sung sẽ không bao giờ làm bạn đau buồn.

+0

Tôi thích địa điểm này. Chỉ cần những gì tôi cần là một tân binh C#/VS.NET. Cảm ơn bạn. – cgyDeveloper

2

Tôi nghĩ rằng bạn chỉ cần đưa ra (giá trị T) sau 'lệnh'.

+0

Trình biên dịch phàn nàn có hoặc không có T. – cgyDeveloper

+0

Hmmm Tôi nghĩ bởi vì câu hỏi này hơi mơ hồ một chút, nhưng tôi nên nhận ra rằng bạn đang cố gắng chuyển đối số cho Hành động. Tôi đồng ý với giải pháp được cung cấp trong Câu trả lời được chấp nhận của bạn, chỉ đơn giản là chuyển một giá trị T (mặc dù không phải trong dấu ngoặc đơn). Nếu bạn có 'giá trị' có sẵn trong khối mã sau đó tôi nghĩ rằng nó sẽ làm việc ok. –

+0

Ah, vâng, tôi tin rằng điều đó cũng có hiệu quả. Cảm ơn vì bạn đã phản hồi. – cgyDeveloper

4

Bạn có nghĩa là:

protected void udpCommand<T>(Action<T> command, T value) {...} 

Với cách gọi:

udpCommand(someUdpCommand, arg); 

Lưu ý rằng điều này có thể làm việc tốt hơn trên C# 3.0, trong đó có mạnh chung suy luận kiểu so với C# 2.0.

+0

Aha! Điều này dường như làm việc ... ít nhất là trình biên dịch không phàn nàn nữa. Ví dụ của Microsoft đã không thực sự bao gồm trường hợp sử dụng của tôi. Rất may tôi đang sử dụng C# 3.0. Số dặm có thể thay đổi trên C# 2.0. – cgyDeveloper

0

Bạn đang cố gắng để làm điều này ...

protected void udpCommand<T>(Action<T> command, T value) 
{ 
    while(!linkDownFail) 
    { 
    try     
    { 
     command(value); 
     // etc. 
    } 
    } 
} 

Sau đó, nó sẽ làm việc như thế này ...

public void ActionWithInt(int param) 
{ 
    // some command 
} 

Action<int> fp = ActionWithInt; 

udpCommand<int>(fp, 10); // or whatever. 
Các vấn đề liên quan