นี่คือ C # 7.0 ซึ่งรองรับฟังก์ชันภายในเครื่อง ....
public static IEnumerable<TSource> DistinctBy<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
{
if (source == null) throw new
ArgumentNullException(nameof(source));
if (keySelector == null) throw
new ArgumentNullException(nameof(keySelector));
// This is basically executing _LocalFunction()
return _LocalFunction();
// This is a new inline method,
// return within this is only within scope of
// this method
IEnumerable<TSource> _LocalFunction()
{
var knownKeys = new HashSet<TKey>(comparer);
foreach (var element in source)
{
if (knownKeys.Add(keySelector(element)))
yield return element;
}
}
}
C # ปัจจุบันกับ Func<T>
public static IEnumerable<TSource> DistinctBy<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
{
if (source == null) throw new
ArgumentNullException(nameof(source));
if (keySelector == null) throw
new ArgumentNullException(nameof(keySelector));
Func<IEnumerable<TSource>> func = () => {
var knownKeys = new HashSet<TKey>(comparer);
foreach (var element in source)
{
if (knownKeys.Add(keySelector(element)))
yield return element;
}
};
// This is basically executing func
return func();
}
เคล็ดลับคือ _ () ถูกประกาศหลังจากใช้งานซึ่งก็ใช้ได้ดี
การใช้ฟังก์ชันท้องถิ่นอย่างเหมาะสม
ตัวอย่างด้านบนเป็นเพียงการสาธิตวิธีการใช้วิธีการอินไลน์ แต่ส่วนใหญ่แล้วถ้าคุณจะเรียกใช้วิธีการเพียงครั้งเดียวก็จะไม่มีประโยชน์
แต่ในตัวอย่างข้างต้นตามที่กล่าวไว้ในความคิดเห็นของPhoshiและLuaanมีข้อได้เปรียบของการใช้ฟังก์ชันท้องถิ่น เนื่องจากฟังก์ชันที่มีผลตอบแทนจะไม่ถูกเรียกใช้งานเว้นแต่จะมีคนทำซ้ำในกรณีนี้เมธอดนอกฟังก์ชันโลคัลจะถูกเรียกใช้และการตรวจสอบพารามิเตอร์จะดำเนินการแม้ว่าจะไม่มีใครทำซ้ำค่าก็ตาม
หลายครั้งที่เรามีโค้ดซ้ำใน method ลองดูตัวอย่างนี้ ..
public void ValidateCustomer(Customer customer){
if( string.IsNullOrEmpty( customer.FirstName )){
string error = "Firstname cannot be empty";
customer.ValidationErrors.Add(error);
ErrorLogger.Log(error);
throw new ValidationError(error);
}
if( string.IsNullOrEmpty( customer.LastName )){
string error = "Lastname cannot be empty";
customer.ValidationErrors.Add(error);
ErrorLogger.Log(error);
throw new ValidationError(error);
}
... on and on...
}
ฉันสามารถเพิ่มประสิทธิภาพนี้ด้วย ...
public void ValidateCustomer(Customer customer){
void _validate(string value, string error){
if(!string.IsNullOrWhitespace(value)){
// i can easily reference customer here
customer.ValidationErrors.Add(error);
ErrorLogger.Log(error);
throw new ValidationError(error);
}
}
_validate(customer.FirstName, "Firstname cannot be empty");
_validate(customer.LastName, "Lastname cannot be empty");
... on and on...
}
return _(); IEnumerable<TSource> _()
?