Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C#

อธิบายแนวคิดของผู้รับมอบสิทธิ์ใน C #


หากคุณเป็นโปรแกรมเมอร์ C ผู้รับมอบสิทธิ์ถือเป็นตัวชี้ไปยังฟังก์ชันได้ อย่างไรก็ตาม ผู้รับมอบสิทธิ์ใน C # เป็นมากกว่าตัวชี้ฟังก์ชันทั่วไป บทความนี้อธิบายแนวคิดของผู้รับมอบสิทธิ์และการนำไปใช้ในการเขียนโปรแกรมแบบวันต่อวัน

โดยพื้นฐานแล้ว ผู้ได้รับมอบหมายให้ระดับของทางอ้อม พวกเขาห่อหุ้มส่วนของรหัสที่สามารถส่งผ่านไปมาและดำเนินการในลักษณะที่ปลอดภัยต่อการพิมพ์ แทนที่จะดำเนินการตามลักษณะการทำงานทันที พฤติกรรมดังกล่าวจะอยู่ในอ็อบเจ็กต์ มีการดำเนินการหลายอย่างที่คุณสามารถดำเนินการกับออบเจ็กต์นั้นได้ และหนึ่งในนั้นกำลังดำเนินการที่มีพฤติกรรมดังกล่าว

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

delegate int Transformer(int x);

เราสามารถกำหนดวิธีการใดๆ (รวมถึง lambdas, instance, หรือ static method) ให้กับอินสแตนซ์ของ Transformer ที่เติมเต็มลายเซ็น ตัวอย่างเช่น −

Transformer square = x => x * x;
Transformer cube = x => x * x * x;

Console.WriteLine(square(3)); // prints 9
Console.WriteLine(cube(5)); // prints 125

ควรใช้ผู้แทนเมื่อใด

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

ในการเขียนโปรแกรม เรามักจะเผชิญกับสถานการณ์ที่เราต้องดำเนินการบางอย่าง แต่เราไม่ทราบล่วงหน้าว่าเราจะต้องการเรียกใช้วิธีการใดเพื่อดำเนินการ ผู้รับมอบสิทธิ์ช่วยเราแก้ปัญหานี้โดยแทนที่พฤติกรรมนั้นด้วยผู้รับมอบสิทธิ์ จากนั้นส่งตัวอย่างที่เป็นรูปธรรมของผู้ได้รับมอบหมายนั้นด้วยพฤติกรรมที่เหมาะสมตามความจำเป็นของบริบทและสถานการณ์

เพื่อให้ผู้รับมอบสิทธิ์ทำอะไรได้ ต้องมีสี่สิ่งเกิดขึ้น –

1) ต้องประกาศประเภทผู้รับมอบสิทธิ์

ประเภทผู้รับมอบสิทธิ์คือคำจำกัดความของฟังก์ชันที่แสดงเป็นหลัก กล่าวคือ ประกอบด้วยประเภทพารามิเตอร์ที่ฟังก์ชันจะยอมรับและประเภทส่งคืนที่ฟังก์ชันดังกล่าวจะส่งคืน

ตัวอย่างเช่น ประเภทผู้รับมอบสิทธิ์ที่แสดงถึงวิธีการที่รับสองตัวเลขเป็นอินพุตและส่งกลับตัวเลขสามารถประกาศเป็น −

delegate int Processor(int numOne, int numTwo);

ตัวประมวลผลเป็นประเภทที่คล้ายกับประเภทที่สร้างโดยคลาส ในการสร้างอินสแตนซ์ประเภทนี้ คุณต้องมีวิธีการที่รับตัวเลขสองตัวเป็นอินพุตและส่งกลับบูล

2) รหัสที่จะดำเนินการต้องอยู่ในวิธีการ

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

static int Add(int numOne, int numTwo){
   Return numOne + numTwo;
}
static int Subtract(int numOne, int numTwo){
   Return numOne - numTwo;
}

3) ต้องสร้างอินสแตนซ์ผู้รับมอบสิทธิ์

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

Processor processorOne = new Processor(Add);
Processor processorTwo = new Processor(Subtract);

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

4) ต้องเรียกใช้อินสแตนซ์ผู้รับมอบสิทธิ์

นี่เป็นเพียงเรื่องของการเรียกใช้เมธอดบนอินสแตนซ์ของผู้รับมอบสิทธิ์ ซึ่งมีชื่อว่า Invoke อย่างไม่น่าแปลกใจ เมธอดนี้บนอินสแตนซ์ผู้รับมอบสิทธิ์มีรายการพารามิเตอร์และประเภทส่งคืนเดียวกันกับที่ประกาศประเภทผู้รับมอบสิทธิ์ระบุ Calling Invoke จะดำเนินการกับอินสแตนซ์ของผู้รับมอบสิทธิ์

int sum = processorOne.Invoke(3, 5);

อย่างไรก็ตาม C # ทำให้ง่ายยิ่งขึ้น คุณสามารถเรียกใช้อินสแตนซ์ผู้รับมอบสิทธิ์ได้โดยตรงราวกับว่ามันเป็นวิธีการในตัวเอง ตัวอย่างเช่น

int difference = processorTwo(10, 6);

การรวมและการลบผู้ได้รับมอบหมาย

หากเราต้องการดำเนินการรายการของการกระทำต่างๆ ด้วยการเรียกใช้อินสแตนซ์ของผู้รับมอบสิทธิ์เพียงครั้งเดียว C# ก็อนุญาตให้เราทำได้ ระบบ. ประเภทผู้รับมอบสิทธิ์มีวิธีการคงที่สองวิธี เรียกว่า รวมและลบ

1. ผสมผสาน

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

public static Delegate Combine(params Delegate[] delegates); // OR
public static Delegate Combine(Delegate a, Delegate b);

หากการดำเนินการใด ๆ ในรายการคำขอมีข้อยกเว้น ซึ่งจะป้องกันไม่ให้มีการดำเนินการใดๆ ต่อจากนี้

2. ลบ

ลบรายการการเรียกใช้ของผู้รับมอบสิทธิ์ที่เกิดขึ้นครั้งล่าสุดออกจากรายการการเรียกใช้ของผู้รับมอบสิทธิ์รายอื่น ส่งกลับผู้รับมอบสิทธิ์ใหม่พร้อมรายการการเรียกใช้ที่สร้างขึ้นโดยนำรายการการเรียกใช้ของแหล่งที่มาและลบรายการการเรียกใช้รายการค่าที่เกิดขึ้นล่าสุด

public static Delegate Remove(Delegate source, Delegate value);

สรุป

  • ผู้รับมอบสิทธิ์สรุปพฤติกรรมด้วยประเภทและชุดของพารามิเตอร์เฉพาะ คล้ายกับอินเทอร์เฟซแบบวิธีเดียว

  • ลายเซ็นประเภทที่อธิบายโดยการประกาศประเภทผู้รับมอบสิทธิ์จะกำหนดวิธีที่สามารถใช้เพื่อสร้างอินสแตนซ์ของผู้รับมอบสิทธิ์และลายเซ็นสำหรับการเรียกใช้

  • การสร้างอินสแตนซ์ผู้รับมอบสิทธิ์ต้องใช้วิธีการที่เราต้องการดำเนินการเมื่อมีการเรียกใช้ผู้รับมอบสิทธิ์

  • อินสแตนซ์ของผู้รับมอบสิทธิ์จะไม่เปลี่ยนรูปแบบ คล้ายกับสตริง

  • อินสแตนซ์ของผู้รับมอบสิทธิ์แต่ละรายการมีรายการคำขอ - รายการการดำเนินการ

  • สามารถรวมและลบอินสแตนซ์ของผู้รับมอบสิทธิ์ออกจากกันได้

ตัวอย่าง

using System;
class Program{
   delegate int Transformer(int x);
   delegate int Processor(int numOne, int numTwo);
   static void Main(){
      Transformer square = x => x * x;
      Transformer cube = x => x * x * x;
      Console.WriteLine(square(3)); // prints 9
      Console.WriteLine(cube(5)); // prints 125
      Processor processorOne = new Processor(Add);
      Processor processorTwo = new Processor(Subtract);
      int sum = processorOne.Invoke(3, 5);
      Console.WriteLine(sum); // prints 8
      int difference = processorTwo(10, 6);
      Console.WriteLine(difference); // prints 4
   }
   static int Add(int numOne, int numTwo){
      return numOne + numTwo;
   }
   static int Subtract(int numOne, int numTwo){
      return numOne - numTwo;
   }
}

ผลลัพธ์

9
125
8
4