mengapa orang membuat pertanyaannya begitu rumit? Jawab saja apa itu delegasi dan apa itu lambda. Berikan penjelasan sebanyak mungkin dan biarkan dia memilih apa saja yang cocok untuknya.
Imir Hoxha
Jawaban:
98
Mereka sebenarnya adalah dua hal yang sangat berbeda. "Delegasi" sebenarnya adalah nama untuk variabel yang menyimpan referensi ke metode atau lambda, dan lambda adalah metode tanpa nama permanen.
Lambda sangat mirip dengan metode lain, kecuali untuk beberapa perbedaan kecil.
Metode normal didefinisikan dalam "pernyataan" dan terikat pada nama permanen, sedangkan lambda didefinisikan "dengan cepat" dalam "ekspresi" dan tidak memiliki nama permanen.
Beberapa lambda dapat digunakan dengan pohon ekspresi .NET, sedangkan metode tidak bisa.
Seorang delegasi didefinisikan seperti ini:
delegate Int32 BinaryIntOp(Int32 x, Int32 y);
Variabel tipe BinaryIntOp dapat memiliki metode atau labmda yang ditetapkan, selama tanda tangannya sama: dua argumen Int32, dan kembalian Int32.
Lambda dapat didefinisikan seperti ini:
BinaryIntOp sumOfSquares = (a, b) => a*a + b*b;
Hal lain yang perlu diperhatikan adalah meskipun tipe Func dan Action generik sering dianggap sebagai "tipe lambda", mereka sama seperti delegasi lainnya. Hal yang menyenangkan tentang mereka adalah bahwa mereka pada dasarnya menentukan nama untuk semua jenis delegasi yang mungkin Anda perlukan (hingga 4 parameter, meskipun Anda pasti dapat menambahkan lebih banyak dari Anda sendiri). Jadi, jika Anda menggunakan berbagai macam tipe delegasi, tetapi tidak lebih dari sekali, Anda dapat menghindari kekacauan kode Anda dengan deklarasi delegasi dengan menggunakan Func dan Action.
Berikut adalah ilustrasi tentang bagaimana Func dan Action "bukan hanya untuk lambda":
Hal lain yang berguna untuk diketahui adalah bahwa tipe delegasi (bukan metodenya sendiri) dengan tanda tangan yang sama tetapi nama yang berbeda tidak akan secara implisit dicor satu sama lain. Ini termasuk delegasi Func and Action. Namun jika tanda tangannya identik, Anda dapat secara eksplisit mentransmisikannya.
Bekerja ekstra .... Dalam fungsi C # fleksibel, dengan penggunaan lambda dan delegasi. Tapi C # tidak memiliki "fungsi kelas satu". Anda dapat menggunakan nama fungsi yang ditetapkan ke variabel delegasi untuk membuat objek yang mewakili fungsi tersebut. Tapi itu benar-benar trik kompiler. Jika Anda memulai pernyataan dengan menulis nama fungsi diikuti dengan titik (misalnya, coba lakukan akses anggota pada fungsi itu sendiri), Anda akan menemukan tidak ada anggota di sana yang dapat dirujuk. Bahkan yang dari Object. Hal ini mencegah pemrogram melakukan hal-hal yang berguna (dan berpotensi berbahaya tentunya) seperti menambahkan metode ekstensi yang dapat dipanggil pada fungsi apa pun. Hal terbaik yang dapat Anda lakukan adalah memperluas kelas Delegasi itu sendiri, yang tentunya juga berguna, tetapi tidak terlalu banyak.
Pembaruan: Lihat juga jawaban Karg yang menggambarkan perbedaan antara delegasi anonim vs. metode & lambda.
Pembaruan 2: James Hart membuat catatan penting, meskipun sangat teknis, bahwa lambda dan delegasi bukanlah entitas .NET (yaitu, CLR tidak memiliki konsep delegasi atau lambda), tetapi mereka adalah kerangka kerja dan konstruksi bahasa.
Penjelasan yang bagus. Meskipun saya pikir yang Anda maksud adalah "fungsi kelas satu", bukan "objek kelas satu". :)
ibz
1
Kamu benar. Saya memiliki kalimat yang terstruktur berbeda selama penulisan ("Fungsi C # sebenarnya bukan objek kelas satu") dan lupa mengubahnya. Terima kasih!
Chris Ammerman
Metode normal didefinisikan dalam "pernyataan" . Pernyataan adalah tindakan dalam urutan program imperatif, mungkin berdasarkan ekspresi. Bukankah definisi metode adalah struktur tata bahasa yang berbeda? Definisi metode tidak terdaftar di docs.microsoft.com/en-us/dotnet/csharp/tour-of-csharp/…
Max Barraclough
32
Pertanyaannya agak ambigu, yang menjelaskan perbedaan besar dalam jawaban yang Anda dapatkan.
Anda sebenarnya bertanya apa perbedaan antara lambda dan delegasi dalam kerangka .NET; itu mungkin salah satu dari beberapa hal. Apakah Anda bertanya:
Apa perbedaan antara ekspresi lambda dan delegasi anonim dalam bahasa C # (atau VB.NET)?
Apa perbedaan antara objek System.Linq.Expressions.LambdaExpression dan objek System.Delegate di .NET 3.5?
Atau sesuatu di antara atau di sekitar ekstrem itu?
Beberapa orang tampaknya mencoba memberi Anda jawaban atas pertanyaan 'apa perbedaan antara ekspresi C # Lambda dan .NET System.Delegate?', Yang tidak terlalu masuk akal.
Kerangka .NET itu sendiri tidak memahami konsep delegasi anonim, ekspresi lambda, atau penutupan - semua itu adalah hal yang ditentukan oleh spesifikasi bahasa. Pikirkan tentang bagaimana compiler C # menerjemahkan definisi metode anonim menjadi metode pada kelas yang dihasilkan dengan variabel anggota untuk menahan status tertutup; ke .NET, tidak ada yang anonim tentang delegasi; itu hanya anonim bagi programmer C # yang menulisnya. Itu sama benarnya dengan ekspresi lambda yang ditugaskan ke tipe delegasi.
Apa .NET TIDAK pahami adalah gagasan delegasi - tipe yang menjelaskan tanda tangan metode, contoh yang mewakili panggilan terikat ke metode tertentu pada objek tertentu, atau panggilan tak terikat ke metode tertentu pada tipe tertentu yang dapat dipanggil objek apa pun dari jenis itu, di mana metode tersebut mengikuti tanda tangan tersebut. Jenis seperti itu semuanya mewarisi dari System.Delegate.
.NET 3.5 juga memperkenalkan namespace System.Linq.Expressions, yang berisi kelas untuk menjelaskan ekspresi kode - dan karena itu juga dapat mewakili panggilan terikat atau tidak terikat ke metode pada jenis atau objek tertentu. Instans LambdaExpression kemudian dapat dikompilasi menjadi delegasi aktual (di mana metode dinamis berdasarkan struktur ekspresi dikodegenkan, dan penunjuk delegasi dikembalikan).
Dalam C # Anda dapat menghasilkan contoh tipe System.Expressions.Expression dengan menetapkan ekspresi lambda ke variabel tipe tersebut, yang akan menghasilkan kode yang sesuai untuk membangun ekspresi pada waktu proses.
Tentu saja, jika memang begitu bertanya apa perbedaan antara ekspresi lambda dan metode anonim di C #, setelah semua, maka semua ini cukup banyak irelevant, dan dalam hal bahwa perbedaan utama adalah singkatnya, yang bersandar ke arah delegasi anonim ketika Anda don' t peduli tentang parameter dan tidak berencana untuk mengembalikan nilai, dan menuju lambda saat Anda ingin mengetikkan parameter yang dirujuk dan jenis kembalian.
Info bagus! Anda menginspirasi saya untuk menyalakan reflektor dan melihat IL. Saya tidak tahu lambda menghasilkan kelas yang dihasilkan, tetapi sangat masuk akal sekarang setelah saya memikirkannya.
Chris Ammerman
21
Satu perbedaan adalah delegasi anonim dapat menghilangkan parameter sementara lambda harus cocok dengan tanda tangan yang tepat. Diberikan:
Anda tidak dapat meneruskan ekspresi lambda yang tidak memiliki parameter atau metode yang tidak memiliki parameter. Ini tidak diperbolehkan:
Test(() => String.Empty); //Not allowed, lambda must match signature
Test(D2); //Not allowed, method must match signatureprivatestringD2()
{
return String.Empty;
}
Delegasi setara dengan function pointers / method pointers / callbacks (pilihlah), dan lambda adalah fungsi anonim yang cukup disederhanakan. Setidaknya itulah yang saya katakan kepada orang-orang.
Persis! Tidak ada perbedaan". Mereka adalah dua hal yang berbeda secara inheren.
ibz
3
Saya tidak memiliki banyak pengalaman dengan ini, tetapi cara saya menggambarkannya adalah bahwa delegasi adalah pembungkus di sekitar fungsi apa pun, sedangkan ekspresi lambda itu sendiri merupakan fungsi anonim.
Delegasi pada dasarnya selalu merupakan penunjuk fungsi. Lambda bisa berubah menjadi delegasi, tetapi juga bisa berubah menjadi pohon ekspresi LINQ. Misalnya,
Func<int, int> f = x => x + 1;
Expression<Func<int, int>> exprTree = x => x + 1;
Baris pertama menghasilkan delegasi, sedangkan baris kedua menghasilkan pohon ekspresi.
Itu benar, tetapi perbedaan di antara keduanya adalah bahwa keduanya adalah konsep yang sama sekali berbeda . Ini seperti membandingkan apel dan jeruk. Lihat jawaban Dan Shield.
ibz
2
lambda hanyalah gula sintaksis pada delegasi. Kompilator akhirnya mengubah lambda menjadi delegasi.
The DelegateTipe parah bernama, meskipun; membuat objek bertipe Delegatesebenarnya membuat variabel yang dapat menampung fungsi - baik itu lambda, metode statis, atau metode kelas.
Saat Anda membuat variabel dengan tipe MyDelegate, itu sebenarnya bukan tipe runtime. Jenis runtime adalah Delegasi. Ada trik kompilator yang terlibat dalam bagaimana delegasi, lambda, dan pohon ekspresi mengkompilasi, yang menurut saya menyebabkan kode menyiratkan hal-hal yang tidak benar.
Chris Ammerman
2
Delegasi adalah referensi ke metode dengan daftar parameter tertentu dan tipe kembalian. Ini mungkin atau mungkin tidak termasuk objek.
Delegasi adalah Antrian penunjuk fungsi, memanggil delegasi dapat memanggil beberapa metode. Lambda pada dasarnya adalah deklarasi metode anonim yang dapat diinterpretasikan oleh kompilator secara berbeda, tergantung pada konteks apa ia digunakan.
Anda bisa mendapatkan delegasi yang menunjuk ke ekspresi lambda sebagai metode dengan mentransmisikannya ke dalam delegasi, atau jika meneruskannya sebagai parameter ke metode yang mengharapkan tipe delegasi tertentu kompilator akan mentransmisikannya untuk Anda. Menggunakannya di dalam pernyataan LINQ, lambda akan diterjemahkan oleh kompilator menjadi pohon ekspresi, bukan hanya sebuah delegasi.
Perbedaan sebenarnya adalah lambda adalah cara singkat untuk mendefinisikan metode di dalam ekspresi lain, sedangkan delegasi adalah tipe objek yang sebenarnya.
Cukup jelas bahwa pertanyaannya adalah "apa perbedaan antara lambda dan delegasi anonim ?" Dari semua jawaban di sini, hanya satu orang yang benar - perbedaan utamanya adalah lambda dapat digunakan untuk membuat pohon ekspresi serta delegasi.
Delegasi sebenarnya hanyalah pengetikan struktural untuk fungsi. Anda dapat melakukan hal yang sama dengan pengetikan nominal dan mengimplementasikan kelas anonim yang mengimplementasikan antarmuka atau kelas abstrak, tetapi itu akan menjadi banyak kode ketika hanya satu fungsi yang dibutuhkan.
Lambda berasal dari ide kalkulus lambda dari Gereja Alonzo pada tahun 1930-an. Ini adalah cara anonim untuk membuat fungsi. Mereka menjadi sangat berguna untuk menyusun fungsi
Jadi sementara beberapa orang mungkin mengatakan lambda adalah gula sintaksis untuk delegasi, saya akan mengatakan delegasi adalah jembatan untuk memudahkan orang menjadi lambda di c #.
Lambdas adalah versi delegasi yang disederhanakan. Mereka memiliki beberapa properti closure seperti delegasi anonim, tetapi juga memungkinkan Anda menggunakan pengetikan tersirat. Lambda seperti ini:
something.Sort((x, y) => return x.CompareTo(y));
jauh lebih ringkas daripada yang dapat Anda lakukan dengan seorang delegasi:
Maksud Anda lambda seperti metode anonim yang disederhanakan (bukan delegasi). Seperti metode (anonim atau tidak), mereka dapat ditugaskan ke variabel delegasi.
Lucas
0
Inilah contoh yang saya pasang di blog saya yang lumpuh. Katakanlah Anda ingin memperbarui label dari utas pekerja. Saya punya 4 contoh cara memperbarui label itu dari 1 menjadi 50 menggunakan delegasi, delegasi langsung dan 2 jenis lambda.
privatevoidbutton2_Click(object sender, EventArgs e)
{
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerAsync();
}
privatedelegatevoidUpdateProgDelegate(int count);
privatevoidUpdateText(int count)
{
if (this.lblTest.InvokeRequired)
{
UpdateProgDelegate updateCallBack = new UpdateProgDelegate(UpdateText);
this.Invoke(updateCallBack, newobject[] { count });
}
else
{
lblTest.Text = count.ToString();
}
}
voidworker_DoWork(object sender, DoWorkEventArgs e)
{
/* Old Skool delegate usage. See above for delegate and method definitions */for (int i = 0; i < 50; i++)
{
UpdateText(i);
Thread.Sleep(50);
}
// Anonymous Method for (int i = 0; i < 50; i++)
{
lblTest.Invoke((MethodInvoker)(delegate()
{
lblTest.Text = i.ToString();
}));
Thread.Sleep(50);
}
/* Lambda using the new Func delegate. This lets us take in an int and
* return a string. The last parameter is the return type. so
* So Func<int, string, double> would take in an int and a string
* and return a double. count is our int parameter.*/
Func<int, string> UpdateProgress = (count) => lblTest.Text = count.ToString();
for (int i = 0; i < 50; i++)
{
lblTest.Invoke(UpdateProgress, i);
Thread.Sleep(50);
}
/* Finally we have a totally inline Lambda using the Action delegate
* Action is more or less the same as Func but it returns void. We could
* use it with parameters if we wanted to like this:
* Action<string> UpdateProgress = (count) => lblT…*/for (int i = 0; i < 50; i++)
{
lblTest.Invoke((Action)(() => lblTest.Text = i.ToString()));
Thread.Sleep(50);
}
}
Saya berasumsi bahwa pertanyaan Anda menyangkut c # dan bukan. NET, karena ambiguitas pertanyaan Anda, karena. NET tidak sendirian - yaitu, tanpa c # - pemahaman delegasi dan ekspresi lambda.
A ( normal , berlawanan dengan apa yang disebut delegasi generik , cf later) delegasi harus dilihat sebagai jenis c ++ typedefdari tipe penunjuk fungsi, misalnya di c ++:
R (*thefunctionpointer) ( T ) ;
typedef adalah tipe thefunctionpointeryang merupakan tipe pointer ke fungsi yang mengambil objek bertipe Tdan mengembalikan objek bertipe R. Anda akan menggunakannya seperti ini:
thefunctionpointer = &thefunction ;
R r = (*thefunctionpointer) ( t ) ; // where t is of type T
di mana thefunctionakan menjadi fungsi yang mengambil Tdan mengembalikan R.
Dalam c # Anda akan pergi
delegate R thedelegate( T t ) ; // and yes, here the identifier t is needed
dan Anda akan menggunakannya seperti ini:
thedelegate thedel = thefunction ;
R r = thedel ( t ) ; // where t is of type T
di mana thefunctionakan menjadi fungsi yang mengambil Tdan mengembalikan R. Ini untuk delegasi, yang disebut delegasi biasa.
Sekarang, Anda juga memiliki delegasi generik di c #, yang merupakan delegasi yang generik, misalnya yang "menggunakan template", dengan demikian menggunakan ekspresi c ++. Mereka didefinisikan seperti ini:
Func<double, double> thefunctor = thefunction2; // call it a functor because it is// really as a functor that you should// "see" itdouble y = thefunctor(2.0);
di mana thefunction2fungsi mengambil sebagai argumen dan mengembalikan a double.
Sekarang bayangkan bahwa alih-alih thefunction2saya ingin menggunakan "fungsi" yang tidak didefinisikan di mana pun untuk saat ini, dengan pernyataan, dan yang tidak akan pernah saya gunakan nanti. Kemudian c # mengijinkan kita untuk menggunakan ekspresi dari fungsi ini. Dengan ekspresi Maksudku "matematika" (atau fungsional, untuk tetap program) ekspresi itu, misalnya: ke double xsaya akan mengasosiasikan dengan doublex*x. Dalam matematika Anda menulis ini menggunakan simbol lateks "\ mapsto" . Dalam c # notasi fungsional telah dipinjam: =>. Misalnya :
Func<double, double> thefunctor = ( (double x) => x * x ); // outer brackets are not// mandatory
(double x) => x * xadalah ekspresi . Ini bukan tipe, sedangkan delegasi (generik atau tidak) adalah.
Moralitas? Pada akhirnya, apa itu delegate (resp. Generic delegate), jika bukan tipe penunjuk fungsi (resp. Dibungkus + jenis penunjuk fungsi pintar + generik), ya? Sesuatu yang lain! Lihat ini dan itu .
Nah, versi yang sangat disederhanakan adalah lambda hanyalah singkatan dari fungsi anonim. Delegasi dapat melakukan lebih dari sekadar fungsi anonim: hal-hal seperti acara, panggilan asinkron, dan beberapa rantai metode.
lambda dapat digunakan sebagai penangan acara; tombol.Click + = (pengirim, eventArgs) => {MessageBox.Show ("Klik"); } dan memanggil System.Threading.Thread (() => Console.Write ("Dieksekusi pada utas")) secara asinkron. Start ();
Jawaban:
Mereka sebenarnya adalah dua hal yang sangat berbeda. "Delegasi" sebenarnya adalah nama untuk variabel yang menyimpan referensi ke metode atau lambda, dan lambda adalah metode tanpa nama permanen.
Lambda sangat mirip dengan metode lain, kecuali untuk beberapa perbedaan kecil.
Seorang delegasi didefinisikan seperti ini:
delegate Int32 BinaryIntOp(Int32 x, Int32 y);
Variabel tipe BinaryIntOp dapat memiliki metode atau labmda yang ditetapkan, selama tanda tangannya sama: dua argumen Int32, dan kembalian Int32.
Lambda dapat didefinisikan seperti ini:
Hal lain yang perlu diperhatikan adalah meskipun tipe Func dan Action generik sering dianggap sebagai "tipe lambda", mereka sama seperti delegasi lainnya. Hal yang menyenangkan tentang mereka adalah bahwa mereka pada dasarnya menentukan nama untuk semua jenis delegasi yang mungkin Anda perlukan (hingga 4 parameter, meskipun Anda pasti dapat menambahkan lebih banyak dari Anda sendiri). Jadi, jika Anda menggunakan berbagai macam tipe delegasi, tetapi tidak lebih dari sekali, Anda dapat menghindari kekacauan kode Anda dengan deklarasi delegasi dengan menggunakan Func dan Action.
Berikut adalah ilustrasi tentang bagaimana Func dan Action "bukan hanya untuk lambda":
Int32 DiffOfSquares(Int32 x, Int32 y) { return x*x - y*y; } Func<Int32, Int32, Int32> funcPtr = DiffOfSquares;
Hal lain yang berguna untuk diketahui adalah bahwa tipe delegasi (bukan metodenya sendiri) dengan tanda tangan yang sama tetapi nama yang berbeda tidak akan secara implisit dicor satu sama lain. Ini termasuk delegasi Func and Action. Namun jika tanda tangannya identik, Anda dapat secara eksplisit mentransmisikannya.
Bekerja ekstra .... Dalam fungsi C # fleksibel, dengan penggunaan lambda dan delegasi. Tapi C # tidak memiliki "fungsi kelas satu". Anda dapat menggunakan nama fungsi yang ditetapkan ke variabel delegasi untuk membuat objek yang mewakili fungsi tersebut. Tapi itu benar-benar trik kompiler. Jika Anda memulai pernyataan dengan menulis nama fungsi diikuti dengan titik (misalnya, coba lakukan akses anggota pada fungsi itu sendiri), Anda akan menemukan tidak ada anggota di sana yang dapat dirujuk. Bahkan yang dari Object. Hal ini mencegah pemrogram melakukan hal-hal yang berguna (dan berpotensi berbahaya tentunya) seperti menambahkan metode ekstensi yang dapat dipanggil pada fungsi apa pun. Hal terbaik yang dapat Anda lakukan adalah memperluas kelas Delegasi itu sendiri, yang tentunya juga berguna, tetapi tidak terlalu banyak.
Pembaruan: Lihat juga jawaban Karg yang menggambarkan perbedaan antara delegasi anonim vs. metode & lambda.
Pembaruan 2: James Hart membuat catatan penting, meskipun sangat teknis, bahwa lambda dan delegasi bukanlah entitas .NET (yaitu, CLR tidak memiliki konsep delegasi atau lambda), tetapi mereka adalah kerangka kerja dan konstruksi bahasa.
sumber
Pertanyaannya agak ambigu, yang menjelaskan perbedaan besar dalam jawaban yang Anda dapatkan.
Anda sebenarnya bertanya apa perbedaan antara lambda dan delegasi dalam kerangka .NET; itu mungkin salah satu dari beberapa hal. Apakah Anda bertanya:
Apa perbedaan antara ekspresi lambda dan delegasi anonim dalam bahasa C # (atau VB.NET)?
Apa perbedaan antara objek System.Linq.Expressions.LambdaExpression dan objek System.Delegate di .NET 3.5?
Atau sesuatu di antara atau di sekitar ekstrem itu?
Beberapa orang tampaknya mencoba memberi Anda jawaban atas pertanyaan 'apa perbedaan antara ekspresi C # Lambda dan .NET System.Delegate?', Yang tidak terlalu masuk akal.
Kerangka .NET itu sendiri tidak memahami konsep delegasi anonim, ekspresi lambda, atau penutupan - semua itu adalah hal yang ditentukan oleh spesifikasi bahasa. Pikirkan tentang bagaimana compiler C # menerjemahkan definisi metode anonim menjadi metode pada kelas yang dihasilkan dengan variabel anggota untuk menahan status tertutup; ke .NET, tidak ada yang anonim tentang delegasi; itu hanya anonim bagi programmer C # yang menulisnya. Itu sama benarnya dengan ekspresi lambda yang ditugaskan ke tipe delegasi.
Apa .NET TIDAK pahami adalah gagasan delegasi - tipe yang menjelaskan tanda tangan metode, contoh yang mewakili panggilan terikat ke metode tertentu pada objek tertentu, atau panggilan tak terikat ke metode tertentu pada tipe tertentu yang dapat dipanggil objek apa pun dari jenis itu, di mana metode tersebut mengikuti tanda tangan tersebut. Jenis seperti itu semuanya mewarisi dari System.Delegate.
.NET 3.5 juga memperkenalkan namespace System.Linq.Expressions, yang berisi kelas untuk menjelaskan ekspresi kode - dan karena itu juga dapat mewakili panggilan terikat atau tidak terikat ke metode pada jenis atau objek tertentu. Instans LambdaExpression kemudian dapat dikompilasi menjadi delegasi aktual (di mana metode dinamis berdasarkan struktur ekspresi dikodegenkan, dan penunjuk delegasi dikembalikan).
Dalam C # Anda dapat menghasilkan contoh tipe System.Expressions.Expression dengan menetapkan ekspresi lambda ke variabel tipe tersebut, yang akan menghasilkan kode yang sesuai untuk membangun ekspresi pada waktu proses.
Tentu saja, jika memang begitu bertanya apa perbedaan antara ekspresi lambda dan metode anonim di C #, setelah semua, maka semua ini cukup banyak irelevant, dan dalam hal bahwa perbedaan utama adalah singkatnya, yang bersandar ke arah delegasi anonim ketika Anda don' t peduli tentang parameter dan tidak berencana untuk mengembalikan nilai, dan menuju lambda saat Anda ingin mengetikkan parameter yang dirujuk dan jenis kembalian.
Dan ekspresi lambda mendukung pembuatan ekspresi.
sumber
Satu perbedaan adalah delegasi anonim dapat menghilangkan parameter sementara lambda harus cocok dengan tanda tangan yang tepat. Diberikan:
public delegate string TestDelegate(int i); public void Test(TestDelegate d) {}
Anda dapat memanggilnya dengan empat cara berikut (perhatikan bahwa baris kedua memiliki delegasi anonim yang tidak memiliki parameter apa pun):
Test(delegate(int i) { return String.Empty; }); Test(delegate { return String.Empty; }); Test(i => String.Empty); Test(D); private string D(int i) { return String.Empty; }
Anda tidak dapat meneruskan ekspresi lambda yang tidak memiliki parameter atau metode yang tidak memiliki parameter. Ini tidak diperbolehkan:
Test(() => String.Empty); //Not allowed, lambda must match signature Test(D2); //Not allowed, method must match signature private string D2() { return String.Empty; }
sumber
Delegasi setara dengan function pointers / method pointers / callbacks (pilihlah), dan lambda adalah fungsi anonim yang cukup disederhanakan. Setidaknya itulah yang saya katakan kepada orang-orang.
sumber
Saya tidak memiliki banyak pengalaman dengan ini, tetapi cara saya menggambarkannya adalah bahwa delegasi adalah pembungkus di sekitar fungsi apa pun, sedangkan ekspresi lambda itu sendiri merupakan fungsi anonim.
sumber
Delegasi pada dasarnya selalu merupakan penunjuk fungsi. Lambda bisa berubah menjadi delegasi, tetapi juga bisa berubah menjadi pohon ekspresi LINQ. Misalnya,
Func<int, int> f = x => x + 1; Expression<Func<int, int>> exprTree = x => x + 1;
Baris pertama menghasilkan delegasi, sedangkan baris kedua menghasilkan pohon ekspresi.
sumber
lambda hanyalah gula sintaksis pada delegasi. Kompilator akhirnya mengubah lambda menjadi delegasi.
Ini sama, saya percaya:
Delegate delegate = x => "hi!"; Delegate delegate = delegate(object x) { return "hi";};
sumber
Delegate
dari 'delegate', yang merupakan kata kunci.Delegasi adalah tanda tangan fungsi; sesuatu seperti
delegate string MyDelegate(int param1);
Delegasi tidak mengimplementasikan badan.
Lambda adalah panggilan fungsi yang cocok dengan tanda tangan delegasi. Untuk delegasi di atas, Anda dapat menggunakan salah satu dari;
(int i) => i.ToString(); (int i) => "ignored i"; (int i) => "Step " + i.ToString() + " of 10";
The
Delegate
Tipe parah bernama, meskipun; membuat objek bertipeDelegate
sebenarnya membuat variabel yang dapat menampung fungsi - baik itu lambda, metode statis, atau metode kelas.sumber
Delegasi adalah referensi ke metode dengan daftar parameter tertentu dan tipe kembalian. Ini mungkin atau mungkin tidak termasuk objek.
Ekspresi lambda adalah bentuk fungsi anonim.
sumber
Delegasi adalah Antrian penunjuk fungsi, memanggil delegasi dapat memanggil beberapa metode. Lambda pada dasarnya adalah deklarasi metode anonim yang dapat diinterpretasikan oleh kompilator secara berbeda, tergantung pada konteks apa ia digunakan.
Anda bisa mendapatkan delegasi yang menunjuk ke ekspresi lambda sebagai metode dengan mentransmisikannya ke dalam delegasi, atau jika meneruskannya sebagai parameter ke metode yang mengharapkan tipe delegasi tertentu kompilator akan mentransmisikannya untuk Anda. Menggunakannya di dalam pernyataan LINQ, lambda akan diterjemahkan oleh kompilator menjadi pohon ekspresi, bukan hanya sebuah delegasi.
Perbedaan sebenarnya adalah lambda adalah cara singkat untuk mendefinisikan metode di dalam ekspresi lain, sedangkan delegasi adalah tipe objek yang sebenarnya.
sumber
Cukup jelas bahwa pertanyaannya adalah "apa perbedaan antara lambda dan delegasi anonim ?" Dari semua jawaban di sini, hanya satu orang yang benar - perbedaan utamanya adalah lambda dapat digunakan untuk membuat pohon ekspresi serta delegasi.
Anda dapat membaca lebih lanjut di MSDN: http://msdn.microsoft.com/en-us/library/bb397687.aspx
sumber
Delegasi sebenarnya hanyalah pengetikan struktural untuk fungsi. Anda dapat melakukan hal yang sama dengan pengetikan nominal dan mengimplementasikan kelas anonim yang mengimplementasikan antarmuka atau kelas abstrak, tetapi itu akan menjadi banyak kode ketika hanya satu fungsi yang dibutuhkan.
Lambda berasal dari ide kalkulus lambda dari Gereja Alonzo pada tahun 1930-an. Ini adalah cara anonim untuk membuat fungsi. Mereka menjadi sangat berguna untuk menyusun fungsi
Jadi sementara beberapa orang mungkin mengatakan lambda adalah gula sintaksis untuk delegasi, saya akan mengatakan delegasi adalah jembatan untuk memudahkan orang menjadi lambda di c #.
sumber
Beberapa dasar di sini. "Delegasi" sebenarnya adalah nama untuk variabel yang memiliki referensi ke metode atau lambda
Ini adalah metode anonim -
(string testString) => { Console.WriteLine(testString); };
Karena metode anonim tidak memiliki nama, kami memerlukan delegasi tempat kami dapat menetapkan kedua metode atau ekspresi ini. Untuk Ex.
delegate void PrintTestString(string testString); // declare a delegate PrintTestString print = (string testString) => { Console.WriteLine(testString); }; print();
Sama dengan ekspresi lambda. Biasanya kami membutuhkan delegasi untuk menggunakannya
s => s.Age > someValue && s.Age < someValue // will return true/false
Kita dapat menggunakan sebuah func delegate untuk menggunakan ekspresi ini.
Func< Student,bool> checkStudentAge = s => s.Age > someValue && s.Age < someValue ; bool result = checkStudentAge ( Student Object);
sumber
Lambdas adalah versi delegasi yang disederhanakan. Mereka memiliki beberapa properti closure seperti delegasi anonim, tetapi juga memungkinkan Anda menggunakan pengetikan tersirat. Lambda seperti ini:
something.Sort((x, y) => return x.CompareTo(y));
jauh lebih ringkas daripada yang dapat Anda lakukan dengan seorang delegasi:
something.Sort(sortMethod); ... private int sortMethod(SomeType one, SomeType two) { one.CompareTo(two) }
sumber
Inilah contoh yang saya pasang di blog saya yang lumpuh. Katakanlah Anda ingin memperbarui label dari utas pekerja. Saya punya 4 contoh cara memperbarui label itu dari 1 menjadi 50 menggunakan delegasi, delegasi langsung dan 2 jenis lambda.
private void button2_Click(object sender, EventArgs e) { BackgroundWorker worker = new BackgroundWorker(); worker.DoWork += new DoWorkEventHandler(worker_DoWork); worker.RunWorkerAsync(); } private delegate void UpdateProgDelegate(int count); private void UpdateText(int count) { if (this.lblTest.InvokeRequired) { UpdateProgDelegate updateCallBack = new UpdateProgDelegate(UpdateText); this.Invoke(updateCallBack, new object[] { count }); } else { lblTest.Text = count.ToString(); } } void worker_DoWork(object sender, DoWorkEventArgs e) { /* Old Skool delegate usage. See above for delegate and method definitions */ for (int i = 0; i < 50; i++) { UpdateText(i); Thread.Sleep(50); } // Anonymous Method for (int i = 0; i < 50; i++) { lblTest.Invoke((MethodInvoker)(delegate() { lblTest.Text = i.ToString(); })); Thread.Sleep(50); } /* Lambda using the new Func delegate. This lets us take in an int and * return a string. The last parameter is the return type. so * So Func<int, string, double> would take in an int and a string * and return a double. count is our int parameter.*/ Func<int, string> UpdateProgress = (count) => lblTest.Text = count.ToString(); for (int i = 0; i < 50; i++) { lblTest.Invoke(UpdateProgress, i); Thread.Sleep(50); } /* Finally we have a totally inline Lambda using the Action delegate * Action is more or less the same as Func but it returns void. We could * use it with parameters if we wanted to like this: * Action<string> UpdateProgress = (count) => lblT…*/ for (int i = 0; i < 50; i++) { lblTest.Invoke((Action)(() => lblTest.Text = i.ToString())); Thread.Sleep(50); } }
sumber
Saya berasumsi bahwa pertanyaan Anda menyangkut c # dan bukan. NET, karena ambiguitas pertanyaan Anda, karena. NET tidak sendirian - yaitu, tanpa c # - pemahaman delegasi dan ekspresi lambda.
A ( normal , berlawanan dengan apa yang disebut delegasi generik , cf later) delegasi harus dilihat sebagai jenis c ++
typedef
dari tipe penunjuk fungsi, misalnya di c ++:typedef adalah tipe
thefunctionpointer
yang merupakan tipe pointer ke fungsi yang mengambil objek bertipeT
dan mengembalikan objek bertipeR
. Anda akan menggunakannya seperti ini:thefunctionpointer = &thefunction ; R r = (*thefunctionpointer) ( t ) ; // where t is of type T
di mana
thefunction
akan menjadi fungsi yang mengambilT
dan mengembalikanR
.Dalam c # Anda akan pergi
delegate R thedelegate( T t ) ; // and yes, here the identifier t is needed
dan Anda akan menggunakannya seperti ini:
thedelegate thedel = thefunction ; R r = thedel ( t ) ; // where t is of type T
di mana
thefunction
akan menjadi fungsi yang mengambilT
dan mengembalikanR
. Ini untuk delegasi, yang disebut delegasi biasa.Sekarang, Anda juga memiliki delegasi generik di c #, yang merupakan delegasi yang generik, misalnya yang "menggunakan template", dengan demikian menggunakan ekspresi c ++. Mereka didefinisikan seperti ini:
public delegate TResult Func<in T, out TResult>(T arg);
Dan Anda dapat menggunakannya seperti ini:
Func<double, double> thefunctor = thefunction2; // call it a functor because it is // really as a functor that you should // "see" it double y = thefunctor(2.0);
di mana
thefunction2
fungsi mengambil sebagai argumen dan mengembalikan adouble
.Sekarang bayangkan bahwa alih-alih
thefunction2
saya ingin menggunakan "fungsi" yang tidak didefinisikan di mana pun untuk saat ini, dengan pernyataan, dan yang tidak akan pernah saya gunakan nanti. Kemudian c # mengijinkan kita untuk menggunakan ekspresi dari fungsi ini. Dengan ekspresi Maksudku "matematika" (atau fungsional, untuk tetap program) ekspresi itu, misalnya: kedouble x
saya akan mengasosiasikan dengandouble
x*x
. Dalam matematika Anda menulis ini menggunakan simbol lateks "\ mapsto" . Dalam c # notasi fungsional telah dipinjam:=>
. Misalnya :Func<double, double> thefunctor = ( (double x) => x * x ); // outer brackets are not // mandatory
(double x) => x * x
adalah ekspresi . Ini bukan tipe, sedangkan delegasi (generik atau tidak) adalah.Moralitas? Pada akhirnya, apa itu delegate (resp. Generic delegate), jika bukan tipe penunjuk fungsi (resp. Dibungkus + jenis penunjuk fungsi pintar + generik), ya? Sesuatu yang lain! Lihat ini dan itu .
sumber
Nah, versi yang sangat disederhanakan adalah lambda hanyalah singkatan dari fungsi anonim. Delegasi dapat melakukan lebih dari sekadar fungsi anonim: hal-hal seperti acara, panggilan asinkron, dan beberapa rantai metode.
sumber