دوال التوسعة (Extension Methods)
جزء من قسم Object Oriented Programming في رحلة C# على Coddy — الدرس 39 من 70.
تتيح لك طرق التوسعة (Extension methods) إضافة طرق جديدة إلى الأنواع الموجودة دون تعديل الكود المصدري الخاص بها أو إنشاء فئات مشتقة. فهي تظهر كما لو كانت طرقاً أصلية للنوع، مما يجعل الكود الخاص بك أكثر قابلية للقراءة وبديهية.
لإنشاء extension method، قم بتعريف static method في static class، مع سبوق المعلمة الأولى بالكلمة المفتاحية this:
public static class StringExtensions
{
public static int WordCount(this string str)
{
return str.Split(' ').Length;
}
}الآن يمكنك استدعاء هذه الطريقة مباشرة على أي سلسلة نصية:
string sentence = "Hello World Today";
int count = sentence.WordCount(); // 3المعلمة this string str تخبر المترجم (compiler) أن هذه الطريقة توسع النوع string. عندما تستدعي sentence.WordCount()، يقوم المترجم بترجمتها إلى StringExtensions.WordCount(sentence) خلف الكواليس.
يمكن لأساليب التوسعة (Extension methods) أيضاً قبول معلمات إضافية:
public static bool IsLongerThan(this string str, int length)
{
return str.Length > length;
}
// الاستخدام
bool result = "Hello".IsLongerThan(3); // trueتُستخدم هذه التقنية بشكل مكثف في LINQ، حيث تُعد أساليب مثل Where() و Select() أساليب توسعة (extension methods) على IEnumerable. تُعد أساليب التوسعة قوية لإضافة وظائف مساعدة إلى الأنواع التي لا تتحكم بها، مما يحافظ على نظافة الكود وتعبيريته.
التحدي
سهللنقم ببناء مجموعة من طرق التوسعة (extension methods) المفيدة للأعداد الصحيحة التي تضيف وظائف ملائمة تتوقع أن تكون مدمجة بالفعل. ستقوم بإنشاء فئة ثابتة (static class) تحتوي على طرق توسعة يمكن استدعاؤها مباشرة على أي عدد صحيح، مما يجعل كودك أكثر تعبيراً وقابلية للقراءة.
ستقوم بتنظيم الكود الخاص بك عبر ملفين:
IntExtensions.cs: أنشئ فئة ثابتة تسمىIntExtensionsداخل مساحة الأسماءUtilities. ستتضمن هذه الفئة طرق توسعة تعزز النوعint:IsEven()- تعيدtrueإذا كان الرقم زوجياً، وfalseخلاف ذلكSquare()- تعيد حاصل ضرب الرقم في نفسهIsInRange(int min, int max)- تعيدtrueإذا كان الرقم بين min و max (بما في ذلك القيمتين)، وfalseخلاف ذلك
thisللمعامل الأول لتحديد النوع الذي تقوم بتوسعته.Program.cs: في ملفك الرئيسي، اقرأ عدداً صحيحاً من المدخلات واستعرض طرق التوسعة الثلاث جميعها. استدعِ كل طريقة مباشرة على العدد الصحيح كما لو كانت طريقة مدمجة، ثم اطبع النتائج.
ستتلقى ثلاثة مدخلات:
- رقم لاختباره (عدد صحيح)
- القيمة الدنيا للتحقق من النطاق (عدد صحيح)
- القيمة القصوى للتحقق من النطاق (عدد صحيح)
اطبع المخرجات بهذا التنسيق:
Is {number} even? {True/False}
Square of {number}: {result}
Is {number} in range [{min}-{max}]? {True/False}على سبيل المثال، إذا كانت المدخلات هي 7، و 5، و 10، يجب أن تكون المخرجات:
Is 7 even? False
Square of 7: 49
Is 7 in range [5-10]? Trueلاحظ مدى الطبيعية التي يمكنك بها كتابة number.IsEven() و number.Square() - تبدو طرق التوسعة وكأنها كانت دائماً جزءاً من نوع العدد الصحيح!
ورقة مرجعية
تسمح لك أساليب التوسعة (Extension methods) بإضافة أساليب جديدة إلى الأنواع الموجودة دون تعديل الكود المصدري الخاص بها. يجب تعريفها كـ static methods في static class، مع سبوق المعلمة الأولى بالكلمة الأساسية this.
بناء الجملة الأساسي لأسلوب التوسعة:
public static class StringExtensions
{
public static int WordCount(this string str)
{
return str.Split(' ').Length;
}
}الاستخدام:
string sentence = "Hello World Today";
int count = sentence.WordCount(); // 3تشير الكلمة الأساسية this قبل المعلمة الأولى إلى النوع الذي يتم توسيعه. يقوم المترجم (compiler) بترجمة sentence.WordCount() إلى StringExtensions.WordCount(sentence).
أساليب التوسعة مع معلمات إضافية:
public static bool IsLongerThan(this string str, int length)
{
return str.Length > length;
}
bool result = "Hello".IsLongerThan(3); // trueجرّب بنفسك
using System;
using Utilities;
class Program
{
public static void Main(string[] args)
{
// قراءة المدخلات
int number = Convert.ToInt32(Console.ReadLine());
int min = Convert.ToInt32(Console.ReadLine());
int max = Convert.ToInt32(Console.ReadLine());
// TODO: استخدم extension methods على 'number' واطبع النتائج
// استدعِ number.IsEven() و number.Square() و number.IsInRange(min, max)
// اطبع بالتنسيق التالي:
// هل {number} زوجي؟ {True/False}
// مربع {number}: {result}
// هل {number} في النطاق [{min}-{max}]؟ {True/False}
}
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس Object Oriented Programming
1أساسيات OOP
الملفات الخارجيةNamespaces والتوجيهاتمقدمة في Classes و Objectsالكلمة المفتاحية 'this'Methods والمعاملاتFields مقابل PropertiesConstructorsObject Initializersمراجعة - آلة حاسبة بسيطة4الوراثة
صيغة الوراثة الأساسية (:)الكلمة المفتاحية 'base'الكلمات المفتاحية Virtual و Overrideالأصناف المختومة (Sealed Classes)الفئة الأساسية 'object'مراجعة - هيكلية الموظفين7ميزات متقدمة
تحميل العوامل (Operator Overloading)المفهرسات (Indexers (this[]))إعادة تعريف ()ToStringدوال التوسعة (Extension Methods)ملخص - Custom List2الخصائص والأعضاء الساكنة (Static Members)
الخصائص المطبقة تلقائيًا (Auto-Implemented Properties)خصائص القراءة فقط والكتابة فقطالحقول والدوال الساكنة (Static)الفئات الساكنة (Static Classes)الأعضاء ذات البنية التعبيرية (Expression-Bodied Members)5تعدد الأشكال والواجهات (Polymorphism & Interfaces)
تعدد الأشكال: وقت التجميع مقابل وقت التشغيلالواجهة مقابل الفئة المجردة (Abstract Class)الواجهات المتعددةالواجهات الصريحةUpcasting و Downcastingملخص - حاسبة الأشكال8مفاهيم البرمجة كائنية التوجه (OOP) المتقدمة
التركيب بدلاً من الوراثةالـ Generics (الأصناف والدوال)الـ Delegates والأحداثالـ Attributes والـ Reflectionواجهة IDisposable وجملة usingأساسيات Dependency Injection