Đại biểu Func không có kiểu trả về


561

Tất cả các đại biểu Func trả về một giá trị. Các đại biểu .NET có thể được sử dụng với các phương thức trả về void là gì?

Câu trả lời:


760

Tất cả các đại biểu Func trả lại một cái gì đó; tất cả các đại biểu hành động trở về khoảng trống.

Func<TResult> không có đối số và trả về TResult:

public delegate TResult Func<TResult>()

Action<T> nhận một đối số và không trả về giá trị:

public delegate void Action<T>(T obj)

Action là đại biểu đơn giản nhất, "trần trụi":

public delegate void Action()

Cũng có Func<TArg1, TResult>Action<TArg1, TArg2>(và những người khác lên đến 16 đối số). Tất cả những thứ này (ngoại trừ Action<T>) đều mới đối với .NET 3.5 (được định nghĩa trong System.Core).


11
FYI, phiên bản tiếp theo của thư viện lớp cơ sở sẽ bao gồm các loại Func và Action hỗ trợ hơn bốn tham số chính thức. Tôi không nhớ chính xác họ lớn như thế nào.
Eric Lippert

88
Trong .NET 4.0 bây giờ họ có tới 8 tham số. Nếu họ giữ điều này, thì trong phiên bản tiếp theo, nó sẽ tăng lên mười một !! 11 !!!
Michiel van Oosterhout

9
Trên thực tế, có vẻ như họ lên tới 16 trong 4.0.
Tustin2121

7
1, 4, 16, 64, 256, 1024, 4096, 16384, 65536, ... điều này chỉ ra rõ ràng rằng trình biên dịch sẽ cần có khả năng đối phó với nhiều đối số cho một chức năng hơn hiện tại trong tương lai !
Chris Morgan

6
Trên thực tế, Tustin2121 đã đúng, họ đã lên tới 16 tham số (cộng với loại trả về trong trường hợp Func<,,, ... ,>) trong .NET 4.0, nhưng tám loại cuối cùng của mỗi "chuỗi" được xác định System.Core.dll, không phải trong mscorlib.dll, vì vậy đó sẽ là lý do Tại sao michielvoo không nhìn thấy chúng. Tuy nhiên, không có thêm Func hay Action nào được thêm vào trong phiên bản .NET 4.5 và 4.5.1. Trình tự này sẽ trở thành A170836 hay A170875 ? Giữ nguyên.
Jeppe Stig Nielsen

83

... không có đối số và có kiểu trả về void?

Tôi tin Actionlà một giải pháp cho việc này.


47

Tất cả các đại biểu Func đều lấy ít nhất một tham số

Đo không phải sự thật. Tất cả đều lấy ít nhất một đối số loại, nhưng đối số đó xác định loại trả về.

Vì vậy, Func<T>chấp nhận không có tham số và trả về một giá trị. Sử dụng Actionhoặc Action<T>khi bạn không muốn trả về một giá trị.


27

Hãy thử System.Func<T>System.Action


1
Tuy nhiên, tôi không nghĩ 0 arg và whatnot tồn tại trong .Net 2.0.
Brian

1
Thật kỳ lạ: Func hoàn toàn không tồn tại trong .Net 2.0, mặc dù Dự đoán và Hành động thì có.
Joel Coehoorn

2
Đối với .NET 2.0, hãy sử dụng ủy quyền của MethodInvoker.
Trevor Elliott

.NET 2 cũng có (hoặc có) một kiểu đại biểu Converter<TInput, TOutput>giống như sau này Func<T, TResult>. Nó được sử dụng trong List<>.ConvertAllphương thức chiếu mọi phần tử List<>vào một đối tượng khác và đặt tất cả các "giá trị hàm" vào một đối tượng mới List<>. (Sau này, người ta thường sử dụng Linq Selectcho điều đó.)
Jeppe Stig Nielsen

0

Đôi khi, bạn sẽ muốn viết một đại biểu để xử lý sự kiện, trong trường hợp đó bạn có thể tận dụng lợi thế System.EvenHandler<T>đó để chấp nhận một đối số kiểu objectbên cạnh tham số thứ hai xuất phát từ đó EventArgs. EventHandlers sẽ trở lạivoid

Cá nhân tôi thấy điều này hữu ích trong quá trình thử nghiệm để tạo một cuộc gọi lại một lần trong cơ thể chức năng.


0

... không có đối số và có kiểu trả về void?

Nếu bạn đang viết System.Windows.Forms, bạn cũng có thể sử dụng:

public delegate void MethodInvoker()

0

Một cách rất dễ dàng để gọi các chương trình con giá trị trả về và không trả về. đang sử dụng FuncAction tương ứng. (xem thêm https://msdn.microsoft.com/en-us/l Library / 018hxwa8 (v = vs.110 ) .aspx )

Hãy thử ví dụ này

using System;

public class Program
{
    private Func<string,string> FunctionPTR = null;  
    private Func<string,string, string> FunctionPTR1 = null;  
    private Action<object> ProcedurePTR = null; 



    private string Display(string message)  
    {  
        Console.WriteLine(message);  
        return null;  
    }  

    private string Display(string message1,string message2)  
    {  
        Console.WriteLine(message1);  
        Console.WriteLine(message2);  
        return null;  
    }  

    public void ObjectProcess(object param)
    {
        if (param == null)
        {
            throw new ArgumentNullException("Parameter is null or missing");
        }
        else 
        {
            Console.WriteLine("Object is valid");
        }
    }


    public void Main(string[] args)  
    {  
        FunctionPTR = Display;  
        FunctionPTR1= Display;  
        ProcedurePTR = ObjectProcess;
        FunctionPTR("Welcome to function pointer sample.");  
        FunctionPTR1("Welcome","This is function pointer sample");   
        ProcedurePTR(new object());
    }  
}

1
Cảm ơn bạn vì đoạn mã này, có thể cung cấp một số trợ giúp hạn chế, ngay lập tức. Một lời giải thích phù hợp sẽ cải thiện đáng kể giá trị lâu dài của nó bằng cách chỉ ra lý do tại sao đây là một giải pháp tốt cho vấn đề và sẽ giúp nó hữu ích hơn cho những người đọc tương lai với những câu hỏi tương tự khác. Vui lòng chỉnh sửa câu trả lời của bạn để thêm một số giải thích, bao gồm các giả định bạn đã thực hiện.
iBug
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.