Func <T> โดยไม่มีพารามิเตอร์


167

ฉันสามารถส่งเมธอดที่มีพารามิเตอร์ out เป็น Func ได้หรือไม่?

public IList<Foo> FindForBar(string bar, out int count) { }

// somewhere else
public IList<T> Find(Func<string, int, List<T>> listFunction) { }

Func ต้องการประเภทเพื่อไม่ให้มีการรวบรวมและการเรียก listFunction ต้องใช้ int และจะไม่อนุญาตให้ใช้

มีวิธีทำเช่นนี้หรือไม่?

คำตอบ:


228

refและoutไม่ได้เป็นส่วนหนึ่งของนิยามพารามิเตอร์ type ดังนั้นคุณจึงไม่สามารถใช้Funcผู้รับมอบสิทธิ์ที่มีอยู่แล้วเพื่อส่งต่อrefและoutอาร์กิวเมนต์ แน่นอนคุณสามารถประกาศผู้แทนของคุณเองหากคุณต้องการ:

delegate V MyDelegate<T,U,V>(T input, out U output);

7
ใน C # 4 (2010) และต่อมา (ไม่ได้เผยแพร่เมื่อคุณเขียนคำตอบของคุณ) เป็นไปได้ที่จะทำเครื่องหมายTว่า contravariant และVเป็น covariant อย่างไรก็ตามเนื่องจากพารามิเตอร์ ( output) ประเภทUจะถูกส่งผ่านโดยการอ้างอิง , Uไม่สามารถทำเครื่องหมายร่วมหรือ contravariant และต้องยังคงอยู่ "คงที่" ดังนั้นควรพิจารณาpublic delegate V MyDelegate<in T, U, out V>(T input, out U output);หากคุณใช้ C # 4 หรือใหม่กว่า
Jeppe Stig Nielsen


24

ทำไมไม่สร้างคลาสเพื่อแค็ปซูลผลลัพธ์?

public class Result
{
     public IList<Foo> List { get; set; }
     public Int32 Count { get; set; }
}

13

Funcครอบครัวของผู้ได้รับมอบหมาย (หรือActionสำหรับเรื่องที่) จะไม่มีอะไร แต่ประเภทผู้รับมอบสิทธิ์ที่เรียบง่ายเช่นการประกาศ

//.NET 4 and above
public delegate TResult Func<out TResult>()
public delegate TResult Func<in T, out TResult>(T obj)

//.NET 3.5
public delegate TResult Func<T1, T2, TResult>(T1 obj1, T2 obj2)
public delegate TResult Func<T1, T2, T3, TResult>(T1 obj1, T2 obj2, T3 obj3)

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

delegate TResult Func<T1, T2, TResult>(T1 obj1, T2 obj2)
delegate TResult Func<T1, T2, TResult>(out T1 obj1, T2 obj2)
delegate TResult Func<T1, T2, TResult>(T1 obj1, out T2 obj2)
delegate TResult Func<T1, T2, TResult>(out T1 obj1, out T2 obj2)

เพียงสองพารามิเตอร์ เรายังไม่ได้แตะต้องrefเลย มันจะยุ่งยากและสับสนสำหรับผู้พัฒนา


2
โปรดทราบว่า C # ฟังก์ชั่นการบรรทุกเกินพิกัดไม่สามารถแยกแยะความแตกต่างระหว่างและdelegate TResult Func<T1, T2, TResult>(T1 obj, T2 obj) delegate TResult Func<T1, T2, TResult>(out T1 obj, T2 obj)ดังนั้นนอกจากจำนวนชื่อสัญลักษณ์โอเวอร์โหลดก็เป็นอีกเหตุผลหนึ่งที่ทำให้ Microsoft ไม่สามารถเพิ่มโอเวอร์โหลดเหล่านี้Funcได้
Kasper van den Berg

มีคนแนะนำฉันไปยังบทความ MSDN เกี่ยวกับผู้รับมอบสิทธิ์ข้างต้นได้หรือไม่?
Su Llewellyn

@SuLlewellyn ฉันไม่พบบทความ msdn ต้นฉบับ แต่คุณสามารถลอง: docs.microsoft.com/en-us/dotnet/api/… , docs.microsoft.com/en-us/dotnet/api/…
nawfal

0

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.