Mendelegasikan fungsi tanpa tipe pengembalian

561

Semua delegasi Fungsi mengembalikan nilai. Apa yang dimaksud dengan delegasi .NET yang dapat digunakan dengan metode yang mengembalikan batal?

Marcel Lamothe
sumber

Jawaban:

760

Semua delegasi Funcar mengembalikan sesuatu; semua delegasi Action kembali batal.

Func<TResult> tidak mengambil argumen dan mengembalikan TResult:

public delegate TResult Func<TResult>()

Action<T> mengambil satu argumen dan tidak mengembalikan nilai:

public delegate void Action<T>(T obj)

Action adalah delegasi 'telanjang' yang paling sederhana:

public delegate void Action()

Ada juga Func<TArg1, TResult>dan Action<TArg1, TArg2>(dan lainnya hingga 16 argumen). Semua ini (kecuali untuk Action<T>) adalah baru untuk. NET 3.5 (didefinisikan dalam System.Core).

Jason
sumber
11
FYI, versi berikutnya dari pustaka kelas dasar akan menyertakan tipe Func dan Action yang mendukung lebih dari empat parameter formal. Saya tidak ingat persis seberapa besar yang mereka dapatkan.
Eric Lippert
88
Dalam. NET 4.0 mereka sekarang naik ke 8 parameter. Jika mereka terus begini, maka di versi selanjutnya akan naik ke sebelas !! 11 !!!
Michiel van Oosterhout
9
Sebenarnya, sepertinya mereka naik ke 16 di 4.0.
Tustin2121
7
1, 4, 16, 64, 256, 1024, 4096, 16384, 65536, ... ini jelas menunjukkan bahwa kompiler harus mampu mengatasi lebih banyak argumen untuk suatu fungsi daripada yang saat ini dilakukan di beberapa titik di masa mendatang. !
Chris Morgan
6
Sebenarnya, Tustin2121 benar, mereka naik ke 16 parameter (ditambah jenis pengembalian dalam kasus Func<,,, ... ,>) di .NET 4.0, tetapi delapan jenis terakhir dari setiap "seri" didefinisikan dalam System.Core.dll, bukan di mscorlib.dll, sehingga akan menjadi alasan mengapa michielvoo tidak melihat mereka. Namun, tidak ada lagi Fungsi atau Tindakan yang ditambahkan dalam .NET versi 4.5 dan 4.5.1. Apakah urutan ini menjadi A170836 atau A170875 ? Tetap disini.
Jeppe Stig Nielsen
83

... tidak mengambil argumen dan memiliki tipe pengembalian tidak sah?

Saya percaya Actionadalah solusi untuk ini.

Marcel Lamothe
sumber
47

Semua delegasi Func mengambil setidaknya satu parameter

Itu tidak benar. Mereka semua mengambil setidaknya satu jenis argumen, tetapi argumen itu menentukan jenis pengembalian.

Jadi Func<T>tidak menerima parameter dan mengembalikan nilai. Gunakan Actionatau Action<T>ketika Anda tidak ingin mengembalikan nilai.

Joel Coehoorn
sumber
27

Coba System.Func<T>danSystem.Action

JaredPar
sumber
1
Saya tidak berpikir 0 arg dan yang lainnya ada di. Net 2.0, meskipun.
Brian
1
Ini aneh: Func tidak ada sama sekali di. Net 2.0, meskipun Predikat dan Tindakan dilakukan.
Joel Coehoorn
2
Untuk .NET 2.0 gunakan delegasi MethodInvoker.
Trevor Elliott
.NET 2 juga memiliki (atau memiliki) tipe delegasi Converter<TInput, TOutput>yang seperti nanti Func<T, TResult>. Itu digunakan dalam List<>.ConvertAllmetode yang memproyeksikan setiap elemen dalam List<>ke objek lain, dan menempatkan semua "nilai fungsi" dalam yang baru List<>. (Belakangan, orang sering menggunakan Linq Selectuntuk itu.)
Jeppe Stig Nielsen
0

Kadang-kadang Anda ingin menulis delegasi untuk penanganan acara, dalam hal ini Anda dapat memanfaatkan System.EvenHandler<T>yang secara implisit menerima argumen tipe objectselain parameter kedua yang harus diturunkan EventArgs. EventHandlers akan kembalivoid

Saya pribadi menemukan ini berguna selama pengujian untuk membuat panggilan balik satu kali di badan fungsi.

AndyG
sumber
0

... tidak mengambil argumen dan memiliki tipe pengembalian tidak sah?

Jika Anda menulis untuk System.Windows.Forms, Anda juga dapat menggunakan:

public delegate void MethodInvoker()
mojmir.novak
sumber
0

Cara yang sangat mudah untuk memanggil subrutin nilai return dan non return. menggunakan Fungsi dan Aksi masing-masing. (lihat juga https://msdn.microsoft.com/en-us/library/018hxwa8(v=vs.110).aspx )

Coba ini contoh ini

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());
    }  
}
Aarón Ibañez Werthermänn
sumber
1
Terima kasih atas cuplikan kode ini, yang mungkin memberikan bantuan terbatas dan segera. Sebuah penjelasan yang tepat akan sangat meningkatkan nilai jangka panjang dengan menunjukkan mengapa ini adalah solusi yang baik untuk masalah ini, dan akan membuatnya lebih bermanfaat untuk pembaca masa depan dengan lainnya, pertanyaan-pertanyaan serupa. Harap edit jawaban Anda untuk menambahkan beberapa penjelasan, termasuk asumsi yang Anda buat.
iBug