ผู้ได้รับมอบหมาย: กริยากับการกระทำและ Func


137

บางคนสามารถให้คำอธิบายที่ดี (หวังว่าจะเป็นตัวอย่าง) ของตัวแทนที่สำคัญที่สุด 3 คนนี้:

  • คำกริยา
  • หนังบู๊
  • func

คำตอบ:


180
  • Predicate: เป็นหลักFunc<T, bool>; ถามคำถาม "การโต้แย้งที่ระบุไม่เป็นไปตามเงื่อนไขที่ผู้ได้รับมอบหมายหรือไม่" ใช้ในสิ่งต่าง ๆ เช่น List.FindAll

  • Action: ดำเนินการตามข้อโต้แย้ง วัตถุประสงค์ทั่วไปมาก ไม่ค่อยได้ใช้มากนักใน LINQ เพราะมันบอกถึงผลข้างเคียงโดยทั่วไป

  • Func: ใช้อย่างกว้างขวางใน LINQ โดยปกติจะแปลงอาร์กิวเมนต์เช่นโดยการฉายโครงสร้างที่ซับซ้อนเป็นคุณสมบัติหนึ่ง

ผู้แทนที่สำคัญอื่น ๆ :

  • EventHandler/ EventHandler<T>: ใช้ทั่ว WinForms

  • Comparison<T>: ชอบIComparer<T>แต่อยู่ในรูปแบบของผู้ได้รับมอบหมาย


3
นอกจากนี้ยังมีSystem.Converter<TInput, TOutput>แม้ว่ามันจะไม่ค่อยได้ใช้
G-Wiz

4
ตัวแปลงเป็นตัวแทนที่ดีเมื่อจำเป็นต้องมีการแปลงแบบจำลองเป็นคลาสธุรกิจเป็นจำนวนมากเช่นstum.de/2009/12/23/…
Michael Stum

EventHandler/EventHandler<T>ปรากฏทั่วนอก WinForms ด้วย
แอนดี้

@Andy: ค่อนข้าง ... แต่น้อยกว่านั้นใน WPF เช่น ฉันยอมรับว่าไม่มีสิ่งใด WinForm ที่เฉพาะเจาะจงกับมัน
Jon Skeet

48

Action, FuncและPredicateทั้งหมดอยู่ในครอบครัวผู้ร่วมประชุม

Action : การดำเนินการสามารถรับพารามิเตอร์ป้อนเข้าได้ แต่จะคืนค่าเป็นโมฆะ

Func: Func สามารถรับพารามิเตอร์อินพุต n แต่จะส่งคืนผลลัพธ์ประเภทที่ให้ไว้เสมอ Func<T1,T2,T3,TResult>ที่นี่ T1, T2, T3 เป็นพารามิเตอร์อินพุตและ TResult คือผลลัพธ์ของมัน

Predicate: เพรดิเคตเป็นรูปแบบของ Func ด้วย แต่จะส่งคืนบูลตลอดเวลา Func<T,bool>ในคำพูดง่ายๆก็คือกระดาษห่อของ


คำตอบที่ดีที่สุดและเรียบง่ายที่สุดที่ฉันเคยพบเกี่ยวกับคำถามนี้
Reyan Chougle

@ReyanChougle: ดีใจที่คุณเห็นว่ามีประโยชน์
ราหุล Garg

9

นอกจากคำตอบของจอนแล้วยังมี

  • Converter<TInput, TOutput>: เป็นหลักFunc<TInput, TOutput>แต่มีความหมาย ใช้โดย List.ConvertAll และ Array.ConvertAll แต่โดยส่วนตัวแล้วยังไม่เห็นที่อื่นเลย

4

MethodInvoker เป็นสิ่งที่ผู้พัฒนา WinForms อาจใช้ มันไม่ยอมรับข้อโต้แย้งและไม่ส่งคืนผลลัพธ์ มันมาก่อน Action และยังคงใช้บ่อยเมื่อเรียกใช้ไปยังเธรด UI ตั้งแต่ BeginInvoke () และ al ยอมรับการมอบหมายที่ไม่ได้พิมพ์ แม้ว่าการกระทำจะทำเช่นกัน

myForm.BeginInvoke((MethodInvoker)delegate
{
  MessageBox.Show("Hello, world...");
});

ฉันยังต้องระวัง ThreadStart และ ParameterizedThreadStart อีกครั้งที่คนส่วนใหญ่จะแทนที่การกระทำในวันนี้


3

เพรดิเคต Func และการกระทำเป็นอินสแตนซ์ของ. NET อินสแตนซ์ของผู้รับมอบสิทธิ์แต่ละรายสามารถอ้างอิงหรือชี้ไปที่วิธีการของผู้ใช้พร้อมลายเซ็นเฉพาะ

ผู้แทนการดำเนินการ - อินสแตนซ์ผู้แทนการดำเนินการอาจชี้ไปที่วิธีที่รับอาร์กิวเมนต์และส่งคืนโมฆะ

ผู้รับมอบสิทธิ์ Func - อินสแตนซ์ของผู้รับมอบสิทธิ์ Func สามารถชี้ไปยังวิธีการที่รับจำนวนตัวแปรของข้อโต้แย้งและคืนค่าบางประเภท

เพรดิเคต - เพรดิเคตจะคล้ายกับอินสแตนซ์ผู้รับมอบสิทธิ์ func และพวกเขาสามารถชี้ไปยังวิธีการที่รับจำนวนตัวแปรของข้อโต้แย้งและส่งกลับประเภทบูล


2

การกระทำและ Func กับแลมบ์ดา:

person p = new person();
Action<int, int> mydel = p.add;       /*(int a, int b) => { Console.WriteLine(a + b); };*/
Func<string, string> mydel1 = p.conc; /*(string s) => { return "hello" + s; };*/
mydel(2, 3);
string s1=  mydel1(" Akhil");
Console.WriteLine(s1);
Console.ReadLine();

2

Func เป็นมิตรกับ LINQ มากขึ้นสามารถส่งผ่านเป็นพารามิเตอร์ได้ (จุดโทษ)

เพรดิเคตไม่สามารถห่ออีกครั้งได้

Predicate<int> IsPositivePred = i => i > 0;
Func<int,bool> IsPositiveFunc = i => i > 0;

new []{2,-4}.Where(i=>IsPositivePred(i)); //Wrap again

new []{2,-4}.Where(IsPositivePred);  //Compile Error
new []{2,-4}.Where(IsPositiveFunc);  //Func as Parameter

2

ตัวอย่างง่ายๆเกี่ยวกับข้อโต้แย้งและสิ่งที่ retutn แต่ละประเภท

Func นี้รับอาร์กิวเมนต์สองตัวและคืนค่า int.Func จะมีประเภทผลตอบแทน

 Func<int, int, int> sum = (a, b) => a + b;
 Console.WriteLine(sum(3, 5));//Print 8

ในกรณีนี้ func ไม่มีอาร์กิวเมนต์ แต่ส่งคืนสตริง

Func<string> print = () => "Hello world";
Console.WriteLine(print());//Print Hello world

การดำเนินการนี้รับอาร์กิวเมนต์สองตัวและคืนค่าเป็นโมฆะ

Action<int, int> displayInput = (x, y) => Console.WriteLine("First number is :" + x + " , Second number is "+ y);
displayInput(4, 6); //Print First number is :4 , Second number is :6

เพรดิเคตนี้รับหนึ่งอาร์กิวเมนต์และส่งคืนบูลเสมอเพรดิเคตทั่วไปจะส่งคืนบูลเสมอ

Predicate<int> isPositive = (x) => x > 0;
Console.WriteLine(isPositive(5));//Print True
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.