แน่นอนเหตุผลที่แท้จริงสำหรับการใช้Func
แทนผู้แทนเฉพาะคือ C # ปฏิบัติต่อผู้ประกาศแยกต่างหากเป็นประเภทที่แตกต่างกันโดยสิ้นเชิง
แม้ว่าFunc<int, bool>
และPredicate<int>
ทั้งคู่จะมีอาร์กิวเมนต์และชนิดส่งคืนเหมือนกัน แต่ก็ไม่เข้ากันได้กับการมอบหมาย ดังนั้นหากทุกไลบรารีประกาศประเภทผู้รับมอบสิทธิ์ของตนเองสำหรับแต่ละรูปแบบของผู้รับมอบสิทธิ์ห้องสมุดเหล่านั้นจะไม่สามารถทำงานร่วมกันได้เว้นแต่ผู้ใช้จะแทรกผู้แทน "bridging" เพื่อทำการแปลง
// declare two delegate types, completely identical but different names:
public delegate void ExceptionHandler1(Exception x);
public delegate void ExceptionHandler2(Exception x);
// a method that is compatible with either of them:
public static void MyExceptionHandler(Exception x)
{
Console.WriteLine(x.Message);
}
static void Main(string[] args)
{
// can assign any method having the right pattern
ExceptionHandler1 x1 = MyExceptionHandler;
// and yet cannot assign a delegate with identical declaration!
ExceptionHandler2 x2 = x1; // error at compile time
}
ด้วยการสนับสนุนให้ทุกคนใช้ Func Microsoft หวังว่าจะช่วยบรรเทาปัญหาประเภทตัวแทนที่เข้ากันไม่ได้ ผู้ได้รับมอบหมายของทุกคนจะเล่นกันอย่างดีเพราะพวกเขาจะถูกจับคู่ตามพารามิเตอร์ / ประเภทผลตอบแทน
ไม่สามารถแก้ปัญหาทั้งหมดได้เนื่องจากFunc
(และAction
) ไม่มีout
หรือref
พารามิเตอร์ แต่ใช้น้อยกว่าปกติ
ปรับปรุง:ในความคิดเห็น Svish พูดว่า:
แต่ถึงกระนั้นการเปลี่ยนประเภทพารามิเตอร์จาก Func เป็น Predicate และย้อนกลับดูเหมือนจะไม่สร้างความแตกต่างใช่ไหม อย่างน้อยก็ยังคงรวบรวมโดยไม่มีปัญหาใด ๆ
ใช่ตราบใดที่โปรแกรมของคุณกำหนดวิธีให้กับผู้ได้รับมอบหมายเท่านั้นในบรรทัดแรกของMain
ฟังก์ชั่นของฉัน คอมไพเลอร์สร้างรหัสไปยังวัตถุผู้รับมอบสิทธิ์ที่ส่งต่อไปยังวิธีการใหม่ ดังนั้นในMain
ฟังก์ชั่นของฉันฉันสามารถเปลี่ยนx1
เป็นประเภทExceptionHandler2
โดยไม่ทำให้เกิดปัญหา
อย่างไรก็ตามในบรรทัดที่สองฉันพยายามกำหนดผู้รับมอบสิทธิ์รายแรกให้ผู้แทนรายอื่น แม้คิดว่าประเภทของผู้ร่วมประชุมครั้งที่ 2 CS0029: Cannot implicitly convert type 'ExceptionHandler1' to 'ExceptionHandler2'
มีตรงเดียวกันพารามิเตอร์และผลตอบแทนประเภทคอมไพเลอร์ให้ข้อผิดพลาด
บางทีนี่อาจทำให้ชัดเจน:
public static bool IsNegative(int x)
{
return x < 0;
}
static void Main(string[] args)
{
Predicate<int> p = IsNegative;
Func<int, bool> f = IsNegative;
p = f; // Not allowed
}
วิธีการของฉันIsNegative
เป็นสิ่งที่ดีอย่างสมบูรณ์ในการกำหนดให้กับp
และf
ตัวแปรตราบใดที่ฉันทำโดยตรง แต่ฉันไม่สามารถกำหนดตัวแปรตัวใดตัวหนึ่งให้กับอีกตัวได้