การขยายอินเทอร์เฟซและชนิดทั่วไป
เพิ่มพฤติกรรมให้ชนิดข้อมูลหลายชนิดได้พร้อมกัน
การขยายอินเทอร์เฟซและชนิดทั่วไป เป็นบทเรียน C# Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน C# Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส C# Academy มีบทเรียนทั้งหมด 4 บทเรียน
การขยายอินเทอร์เฟซ
คุณสามารถเขียนเมธอดส่วนขยายที่มีพารามิเตอร์ this เป็น อินเทอร์เฟซ ได้ ทุกชนิดที่ใช้อินเทอร์เฟซนั้นจะมีเมธอดนี้เพิ่มขึ้นทันที นี่คือวิธีที่ LINQ เพิ่มเมธอดจำนวนมากให้กับ IEnumerable<T>
ส่วนขยายแบบทั่วไปบน IEnumerable
การทำให้เมธอดเป็นแบบทั่วไปเหนือ T และขยาย IEnumerable<T> ทำให้ตัวช่วยนี้ใช้ได้กับลำดับทุกชนิด ทั้งรายการ อาร์เรย์ ผลลัพธ์จากการสืบค้น และอื่น ๆ
using System;
using System.Collections.Generic;
public static class EnumerableExtensions
{
public static bool IsEmpty<T>(this IEnumerable<T> source)
{
foreach (var item in source) return false;
return true;
}
}
public class Program
{
public static void Main()
{
var nums = new List<int> { 1, 2, 3 };
Console.WriteLine(nums.IsEmpty());
Console.WriteLine(new int[0].IsEmpty());
}
}การวนซ้ำในลำดับ
ภายในส่วนขยาย คุณสามารถปฏิบัติต่อพารามิเตอร์เสมือนเป็น IEnumerable<T> ใด ๆ ได้ ที่นี่เราคำนวณผลรวมโดยไม่พึ่งพา LINQ
using System;
using System.Collections.Generic;
public static class EnumerableExtensions
{
public static int SumValues(this IEnumerable<int> source)
{
int total = 0;
foreach (var n in source) total += n;
return total;
}
}
public class Program
{
public static void Main()
{
var nums = new List<int> { 10, 20, 30 };
Console.WriteLine(nums.SumValues());
}
}การส่งคืนลำดับใหม่
ส่วนขยายสามารถส่งคืนลำดับได้เช่นกัน เมื่อใช้ร่วมกับ yield return ส่วนขยายเหล่านี้จะกลายเป็นตัวดำเนินการรูปแบบ LINQ ที่ประเมินเมื่อจำเป็น
using System;
using System.Collections.Generic;
public static class EnumerableExtensions
{
public static IEnumerable<T> EveryOther<T>(this IEnumerable<T> source)
{
bool take = true;
foreach (var item in source)
{
if (take) yield return item;
take = !take;
}
}
}
public class Program
{
public static void Main()
{
var letters = new List<string> { "a", "b", "c", "d", "e" };
foreach (var l in letters.EveryOther())
Console.WriteLine(l);
}
}ข้อจำกัดของชนิดข้อมูลทั่วไป
คุณสามารถกำหนดข้อจำกัดให้พารามิเตอร์ชนิดข้อมูลทั่วไป เพื่อบังคับให้มีความสามารถที่ต้องการได้ ในที่นี้ where T : IComparable<T> ทำให้เราเปรียบเทียบรายการเพื่อหาค่าสูงสุดได้
using System;
using System.Collections.Generic;
public static class EnumerableExtensions
{
public static T MaxItem<T>(this IEnumerable<T> source) where T : IComparable<T>
{
bool started = false;
T best = default;
foreach (var item in source)
{
if (!started || item.CompareTo(best) > 0) { best = item; started = true; }
}
return best;
}
}
public class Program
{
public static void Main()
{
var nums = new List<int> { 3, 9, 1, 7 };
Console.WriteLine(nums.MaxItem());
}
}การขยายอินเทอร์เฟซแบบกำหนดเอง
อินเทอร์เฟซที่คุณสร้างขึ้นเองก็ได้รับประโยชน์เช่นกัน ให้กำหนดอินเทอร์เฟซ แล้วเพิ่มพฤติกรรมที่ใช้ร่วมกันผ่านส่วนขยาย แทนการทำซ้ำในทุกคลาสที่นำไปใช้
using System;
public interface INamed { string Name { get; } }
public class Dog : INamed { public string Name => "Rex"; }
public static class NamedExtensions
{
public static string Greeting(this INamed n) => "Hello, " + n.Name;
}
public class Program
{
public static void Main()
{
var d = new Dog();
Console.WriteLine(d.Greeting());
}
}พารามิเตอร์ชนิดข้อมูลหลายตัว
ส่วนขยายสามารถใช้พารามิเตอร์ชนิดข้อมูลทั่วไปได้หลายตัว ตัวช่วยฉายข้อมูลนี้จะแปลงลำดับโดยใช้ฟังก์ชัน คล้ายกับ Select ใน LINQ
using System;
using System.Collections.Generic;
public static class EnumerableExtensions
{
public static IEnumerable<TResult> Map<TSource, TResult>(
this IEnumerable<TSource> source, Func<TSource, TResult> f)
{
foreach (var item in source) yield return f(item);
}
}
public class Program
{
public static void Main()
{
var nums = new List<int> { 1, 2, 3 };
foreach (var s in nums.Map(n => "#" + n))
Console.WriteLine(s);
}
}การทำงานร่วมกับ LINQ ในตัว
เมธอดส่วนขยายของคุณสามารถทำงานร่วมกับ LINQ ได้ คุณสามารถเชื่อมต่อตัวดำเนินการที่กำหนดเองเข้ากับตัวดำเนินการมาตรฐานในกระบวนการประมวลผลต่อเนื่องเดียวกันได้
using System;
using System.Collections.Generic;
using System.Linq;
public static class EnumerableExtensions
{
public static IEnumerable<T> EveryOther<T>(this IEnumerable<T> source)
{
bool take = true;
foreach (var item in source) { if (take) yield return item; take = !take; }
}
}
public class Program
{
public static void Main()
{
var nums = Enumerable.Range(1, 10);
var result = nums.Where(n => n > 2).EveryOther().ToList();
Console.WriteLine(string.Join(", ", result));
}
}การขยาย IEnumerable ครอบคลุมหลายชนิด
เนื่องจากอาร์เรย์ รายการ พจนานุกรม เซตแฮช และผลลัพธ์จากการสืบค้น ล้วนนำ IEnumerable<T> ไปใช้ ส่วนขยายเดียวจึงครอบคลุมทั้งหมดได้ในคราวเดียว
using System;
using System.Collections.Generic;
public static class EnumerableExtensions
{
public static int CountItems<T>(this IEnumerable<T> source)
{
int n = 0;
foreach (var item in source) n++;
return n;
}
}
public class Program
{
public static void Main()
{
Console.WriteLine(new[] { 1, 2, 3 }.CountItems());
Console.WriteLine(new HashSet<string> { "a", "b" }.CountItems());
}
}เหตุผลที่แนวทางนี้ขยายได้ดี
ส่วนขยายของอินเทอร์เฟซช่วยให้คุณสร้างตัวช่วยแบบพหุรูปได้โดยไม่ต้องสืบทอด เขียนตรรกะเพียงครั้งเดียวโดยอิงกับอินเทอร์เฟซ แล้วคลาสที่นำไปใช้ทุกคลาสทั้งในปัจจุบันและอนาคตจะได้รับความสามารถนี้โดยไม่ต้องทำอะไรเพิ่มเติม
using System;
using System.Collections.Generic;
public static class EnumerableExtensions
{
public static string JoinWith<T>(this IEnumerable<T> source, string sep)
{
return string.Join(sep, source);
}
}
public class Program
{
public static void Main()
{
var nums = new List<int> { 1, 2, 3 };
Console.WriteLine(nums.JoinWith(" -> "));
}
}ลองทำด้วยตัวเอง
สร้างตัวดำเนินการชนิดข้อมูลทั่วไปขนาดเล็กบน IEnumerable<T> แล้วเชื่อมต่อเข้ากับ LINQ สังเกตว่าตัวดำเนินการนี้ทำงานกับลำดับทุกชนิดได้อย่างไร
using System;
using System.Collections.Generic;
using System.Linq;
public static class EnumerableExtensions
{
public static IEnumerable<T> WithoutDuplicatesByKey<T, TKey>(
this IEnumerable<T> source, Func<T, TKey> keySelector)
{
var seen = new HashSet<TKey>();
foreach (var item in source)
if (seen.Add(keySelector(item))) yield return item;
}
}
public class Program
{
public static void Main()
{
var words = new[] { "apple", "avocado", "banana", "cherry", "blueberry" };
var firstPerLetter = words.WithoutDuplicatesByKey(w => w[0]);
Console.WriteLine(string.Join(", ", firstPerLetter));
}
}ตรวจสอบอย่างรวดเร็ว
ลองคิดดูว่าส่วนขยายรูปแบบ LINQ ถูกประกาศอย่างไร
สรุปทบทวน
การขยายอินเทอร์เฟซ โดยเฉพาะ IEnumerable<T> เป็นรากฐานของการเขียนโปรแกรมรูปแบบ LINQ
- ทำให้เมธอดเป็นชนิดข้อมูลทั่วไป และใช้อินเทอร์เฟซเป็นชนิด
this - ใช้
yield returnเพื่อสร้างตัวดำเนินการที่ประเมินเมื่อจำเป็น - ใช้ข้อจำกัดแบบ
whereเพื่อบังคับให้มีความสามารถ เช่นIComparable<T> - ส่วนขยายของอินเทอร์เฟซเดียวครอบคลุมคลาสที่นำไปใช้ทั้งหมด รวมถึงคลาสที่จะมีในอนาคต
คำถามที่พบบ่อย
บทเรียน “การขยายอินเทอร์เฟซและชนิดทั่วไป” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การขยายอินเทอร์เฟซและชนิดทั่วไป” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C# Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C# Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การขยายอินเทอร์เฟซและชนิดทั่วไป”
เพิ่มพฤติกรรมให้ชนิดข้อมูลหลายชนิดได้พร้อมกัน คุณปฏิบัติ C# Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน C# Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน C# Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน
บทเรียน “การขยายอินเทอร์เฟซและชนิดทั่วไป” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน C# Academy นี้ได้ไหม
ได้ บทเรียน C# Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การกำหนดเมธอดส่วนขยาย
- การขยายอินเทอร์เฟซและชนิดทั่วไป
- การค้นหาเมธอดส่วนขยาย
- การออกแบบส่วนขยายที่ดี