0Pricing
C# Academy · درس

حلّ Extension Methods

افهموا كيفية عثور المصرّف على الامتدادات

حلّ Extension Methods درس مجاني في C# Academy على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في C# Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة C# Academy 4 دروس في المجموع.

كيف يعثر المصرّف على الامتدادات

عندما تكتبون value.Method() ولا توجد أسلوب مثيل مطابق، يبحث المصرّف عن أسلوب امتداد. لكنه لا يأخذ في الحسبان إلا الامتدادات التي تكون مساحة الأسماء الحاوية لها قيد النطاق من خلال توجيه using.

تُدخل توجيهات using الامتدادات إلى النطاق

لا يظهر الامتداد إلا إذا استوردتم مساحة الأسماء الخاصة به. ومن دون توجيه using الصحيح، يبدو الأسلوب غير موجود، مع أنه مجمّع داخل assembly.

using System;
using MyHelpers; // brings StringExtensions into scope

namespace MyHelpers
{
    public static class StringExtensions
    {
        public static string Reverse(this string s)
        {
            var arr = s.ToCharArray();
            Array.Reverse(arr);
            return new string(arr);
        }
    }
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine("hello".Reverse());
    }
}

يُفحَص أسلوب المثيل أولًا

يحلّ المصرّف الاستدعاء على مراحل: يبحث أولًا عن أسلوب مثيل مطابق، بما في ذلك الأساليب الموروثة. ولا يبحث عن أساليب الامتداد إلا إذا لم يجد أسلوبًا مناسبًا.

using System;
using System.Collections.Generic;

public static class ListExt
{
    // Ignored: List<int> already has Add(int)
    public static void Add(this List<int> list, int a, int b)
        => list.Add(a + b);
}

public class Program
{
    public static void Main()
    {
        var list = new List<int>();
        list.Add(5); // the built-in instance Add wins for this signature
        Console.WriteLine(list[0]);
    }
}

تُفضَّل مساحات الأسماء الأقرب

إذا تطابق امتدادان، يفوز الامتداد الذي تكون مساحة أسمائه أقرب في التسلسل الهرمي للتضمين. وإذا تعذّر على المصرّف حسم الغموض، يحدث خطأ في الترجمة، ما يفرض عليكم إزالة الالتباس.

using System;

namespace Outer
{
    public static class A { public static string Tag(this int n) => "A" + n; }

    namespace Inner
    {
        public static class B { public static string Tag(this int n) => "B" + n; }

        public class Program
        {
            public static void Main()
            {
                // B is in the nearer (Inner) namespace, so it is preferred
                Console.WriteLine(7.Tag());
            }
        }
    }
}

إزالة الالتباس باستخدام استدعاء ثابت

عند تعارض الامتدادات أو عندما تريدون التصريح بالاختيار، استدعوا الأسلوب الثابت مباشرة باستخدام اسم الصنف الكامل. يتجاوز ذلك عملية حلّ الامتدادات بالكامل.

using System;

public static class FormatExt
{
    public static string Bracket(this string s) => "[" + s + "]";
}

public class Program
{
    public static void Main()
    {
        // Explicit static call, no ambiguity possible
        Console.WriteLine(FormatExt.Bracket("x"));
    }
}

حل التحميل الزائد بين الامتدادات

إذا اشتركت عدة أساليب امتداد في الاسم نفسه، يختار الحل المعتاد للتحميل الزائد أفضل تطابق وفقًا لأنواع المعلمات، تمامًا كما يحدث في التحميل الزائد العادي للأساليب.

using System;

public static class PrintExt
{
    public static string Describe(this int n) => "int:" + n;
    public static string Describe(this string s) => "str:" + s;
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine(42.Describe());
        Console.WriteLine("hi".Describe());
    }
}

استنتاج الأنواع العامة أثناء الحل

بالنسبة إلى الامتدادات العامة، يستنتج المصرّف معاملات الأنواع من الكائن المستقبل والمعلمات. وإذا فشل الاستنتاج، فلا يؤخذ الامتداد في الحسبان.

using System;
using System.Collections.Generic;

public static class SeqExt
{
    public static T FirstItem<T>(this IEnumerable<T> source)
    {
        foreach (var item in source) return item;
        throw new InvalidOperationException("empty");
    }
}

public class Program
{
    public static void Main()
    {
        var nums = new List<int> { 5, 6, 7 };
        // T inferred as int from the List<int> receiver
        Console.WriteLine(nums.FirstItem());
    }
}

global using والاستيرادات الضمنية

تتيح C# الحديثة تعريف توجيهات global using بحيث تكون مساحة الأسماء قيد النطاق في كامل المشروع. ويجعل ذلك مكتبات الامتدادات المشتركة متاحة في كل مكان من دون تكرار عمليات الاستيراد.

using System;

// In a real project a separate file might say: global using MyHelpers;
namespace MyHelpers
{
    public static class IntExt { public static int Twice(this int n) => n * 2; }
}

public class Program
{
    public static void Main()
    {
        // Works here because MyHelpers is referenced explicitly
        Console.WriteLine(MyHelpers.IntExt.Twice(8));
    }
}

متى يكون نوع الكائن المستقبل مهمًا

يعتمد الحل على النوع الساكن للكائن المستقبل، لا على نوعه أثناء التشغيل. وينطبق الامتداد المعرّف لنوع أساسي حتى عندما يحتوي المتغير على مثيل من نوع مشتق، ما لم يكن هناك امتداد أكثر تخصيصًا قيد النطاق.

using System;

public class Animal { }
public class Cat : Animal { }

public static class AnimalExt
{
    public static string Kind(this Animal a) => "animal";
}

public class Program
{
    public static void Main()
    {
        Animal a = new Cat();
        // Chosen by static type Animal
        Console.WriteLine(a.Kind());
    }
}

نموذج ذهني للحل

تصوّروا الترتيب كما يلي: (1) أساليب المثيل، ثم (2) أساليب الامتداد من مساحات الأسماء المستوردة، بدءًا بالأقرب، ثم (3) حل التحميل الزائد بين المرشحين. يفسّر فهم هذا الترتيب تقريبًا كل نتيجة مفاجئة.

using System;

public static class Ext
{
    public static string Wrap(this string s) => "<" + s + ">";
}

public class Program
{
    public static void Main()
    {
        // No instance Wrap exists, so the extension is used
        Console.WriteLine("node".Wrap());
    }
}

جرّبوا بأنفسكم

عرّفوا امتدادًا داخل مساحة أسماء، واستوردوها، ثم استدعوه. بعد ذلك استدعوا الأسلوب نفسه صراحةً بوصفه أسلوبًا ثابتًا لتروا أن الطريقتين تعملان.

using System;
using Text.Helpers;

namespace Text.Helpers
{
    public static class StringExtensions
    {
        public static int Vowels(this string s)
        {
            int count = 0;
            foreach (var c in s.ToLower())
                if ("aeiou".IndexOf(c) >= 0) count++;
            return count;
        }
    }
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine("education".Vowels());
        Console.WriteLine(Text.Helpers.StringExtensions.Vowels("education"));
    }
}

تحقق سريع

فكّروا في العوامل التي تجعل أسلوب الامتداد ظاهرًا.

مراجعة

يتبع حل أساليب الامتداد ترتيبًا واضحًا.

  • تُجرَّب أساليب المثيل أولًا؛ ولا تتدخل الامتدادات إلا لسد الفجوات.
  • لا يظهر الامتداد إلا إذا كانت مساحة أسمائه قيد النطاق عبر using أو global using.
  • تفوز مساحات الأسماء الأقرب؛ وتؤدي حالات التعادل التي يتعذر حسمها إلى أخطاء في الترجمة.
  • يمكنكم دائمًا استدعاء الأسلوب الثابت صراحةً لإزالة الالتباس.
  • يستخدم الحل النوع الساكن للكائن المستقبل.

الأسئلة الشائعة

هل درس «حلّ Extension Methods» مجاني؟

نعم — نص درس «حلّ Extension Methods» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة C# Academy، انتقل إلى CoddyKit PRO. تتضمن دورة C# Academy 4 دروس في المجموع.

ماذا ستتعلم في «حلّ Extension Methods»؟

افهموا كيفية عثور المصرّف على الامتدادات تتمرن على C# Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ C# Academy؟

لا تُشترط خبرة سابقة. C# Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.

كم من الوقت يستغرق درس «حلّ Extension Methods»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس C# Academy هذا؟

نعم. كل درس في C# Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. تعريف Extension Methods
  2. توسيع الواجهات والأنواع العامة
  3. حلّ Extension Methods
  4. تصميم امتدادات جيدة
← العودة إلى C# Academy