تنفيذ الفئات باستخدام فئات جزئية

مكتمل

من الممكن تقسيم تعريف فئة أو أسلوب على ملفين أو أكثر من ملفات المصدر. يحتوي كل ملف مصدر على مقطع من نوع أو تعريف الأسلوب، ويتم دمج جميع الأجزاء عند تحويل التطبيق برمجيا.

فئات جزئية

هناك العديد من الحالات التي يكون فيها تقسيم تعريف الفئة مرغوبا فيه:

  • يمكن الإعلان عن فئة على ملفات منفصلة العديد من المبرمجين من العمل عليها في نفس الوقت.
  • يمكنك إضافة تعليمة برمجية إلى الفئة دون الحاجة إلى إعادة إنشاء الملف المصدر الذي يتضمن المصدر الذي تم إنشاؤه تلقائيا. يستخدم Visual Studio هذا الأسلوب عند إنشاء Windows Forms ورمز برنامج تضمين خدمة ويب وما إلى ذلك. يمكنك إنشاء التعليمات البرمجية التي تستخدم هذه الفئات دون الحاجة إلى تعديل الملف الذي تم إنشاؤه بواسطة Visual Studio.
  • يمكن أن تولد مولدات المصدر وظائف إضافية في فئة.

لتقسيم تعريف فئة، استخدم معدل الكلمة الأساسية الجزئية. في الممارسة العملية، يتم تعريف كل فئة جزئية عادة في ملف منفصل، مما يسهل إدارة الفئة وتوسيعها بمرور الوقت.

يوضح المثال Employee التالي كيفية تقسيم الفئة عبر ملفين: Employee_Part1.csEmployee_Part2.cs.


// This is in Employee_Part1.cs
public partial class Employee
{
    public void DoWork()
    {
        Console.WriteLine("Employee is working.");
    }
}


// This is in Employee_Part2.cs
public partial class Employee
{
    public void GoToLunch()
    {
        Console.WriteLine("Employee is at lunch.");
    }
}


//Main program demonstrating the Employee class usage
public class Program
{
    public static void Main()
    {
        Employee emp = new Employee();
        emp.DoWork();
        emp.GoToLunch();
    }
}

// Expected Output:
// Employee is working.
// Employee is at lunch.

تشير الكلمة الأساسية partial إلى أنه يمكن تعريف أجزاء أخرى من الفئة في مساحة الاسم. يجب أن تستخدم جميع الأجزاء الكلمة الأساسية partial. يجب أن تكون جميع الأجزاء متوفرة في وقت التحويل البرمجي لتشكيل النوع النهائي. يجب أن تتمتع جميع الأجزاء بنفس إمكانية الوصول، مثل publicprivateوما إلى ذلك.

إذا تم الإعلان عن أي جزء مجرد، فإن النوع بأكمله يعتبر مجردا. إذا تم الإعلان عن أي جزء مختوم، فإن النوع بأكمله يعتبر مختوما. إذا أعلن أي جزء عن نوع أساسي، فإن النوع بأكمله يرث تلك الفئة.

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

ملاحظه

لا يتوفر معدل partial في إعلانات التفويض أو التعداد.

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


class Container
{
    partial class Nested
    {
        void Test() { }
    }

    partial class Nested
    {
        void Test2() { }
    }
}

في وقت التحويل البرمجي، يتم دمج سمات تعريفات النوع الجزئي. على سبيل المثال، ضع في اعتبارك الإعلانات التالية:


[SerializableAttribute]
partial class Moon { }

[ObsoleteAttribute]
partial class Moon { }

وهي مكافئة للإعلانات التالية:


[SerializableAttribute]
[ObsoleteAttribute]
class Moon { }

يتم دمج ما يلي من جميع تعريفات النوع الجزئي:

  • تعليقات XML. ومع ذلك، إذا تضمن إعلانا العضو الجزئي تعليقات، يتم تضمين التعليقات من العضو المنفذ فقط.
  • واجهات
  • سمات معلمة النوع العام
  • سمات الفئة
  • اعضاء

على سبيل المثال، ضع في اعتبارك الإعلانات التالية:


partial class Earth : Planet, IRotate { }
partial class Earth : IRevolve { }

وهي مكافئة للإعلانات التالية:


class Earth : Planet, IRotate, IRevolve { }

القيود المفروضة على تعريفات الفئات الجزئية

هناك العديد من القواعد التي يجب اتباعها عند العمل مع تعريفات فئة جزئية:

  • يجب تعديل جميع تعريفات النوع الجزئي التي يقصد بها أن تكون أجزاء من نفس النوع بجزئي. على سبيل المثال، تنشئ إعلانات الفئة التالية خطأ:

    
    public partial class A { }
    //public class A { }  // Error, must also be marked partial
    
    
  • يمكن أن يظهر المعدل الجزئي مباشرة فقط قبل فئة الكلمة الأساسية أو البنية أو الواجهة.

  • يسمح بالأنواع الجزئية المتداخلة في تعريفات النوع الجزئي كما هو موضح في المثال التالي:

    
    partial class ClassWithNestedClass
    {
        partial class NestedClass { }
    }
    
    partial class ClassWithNestedClass
    {
        partial class NestedClass { }
    }
    
    
  • يجب تعريف جميع تعريفات النوع الجزئي التي يقصد بها أن تكون أجزاء من نفس النوع في نفس التجميع ونفس الوحدة النمطية (.exe أو ملف .dll). لا يمكن أن تمتد التعريفات الجزئية على وحدات نمطية متعددة.

  • يجب أن يتطابق اسم الفئة ومعلمات النوع العام مع جميع تعريفات النوع الجزئي. يمكن أن تكون الأنواع العامة جزئية. يجب أن يستخدم كل إعلان جزئي نفس أسماء المعلمات بنفس الترتيب.

  • الكلمات الأساسية التالية في تعريف نوع جزئي اختيارية، ولكن إذا كانت موجودة في تعريف نوع جزئي واحد، يجب تحديد نفس التعريف الجزئي الآخر لنفس النوع:

    • علني
    • عسكري
    • محمي
    • داخلي
    • تجريدي
    • سدود
    • الفئة الأساسية
    • معدل جديد (أجزاء متداخلة)
    • القيود العامة

تنفيذ فئات جزئية

في المثال التالي، يتم تعريف الحقول والمنشئ للفئة Coords في تعريف فئة جزئية واحدة (Coords_Part1.cs)، ويتم تعريف الأسلوب PrintCoords في تعريف فئة جزئية آخر (Coords_Part2.cs). يوضح هذا الفصل كيف يمكن تقسيم الفئات الجزئية عبر ملفات متعددة لتسهيل الصيانة.


// This is in Coords_Part1.cs
 public partial class Coords
 {
     private int x;
     private int y;

     public Coords(int x, int y)
     {
         this.x = x;
         this.y = y;
     }
 }

 // This is in Coords_Part2.cs
 public partial class Coords
 {
     public void PrintCoords()
     {
         Console.WriteLine("Coords: {0},{1}", x, y);
     }
 }

// Main program demonstrating the Coords class usage
 class TestCoords
 {
     static void Main()
     {
         Coords myCoords = new Coords(10, 15);
         myCoords.PrintCoords();

         // Keep the console window open in debug mode.
         Console.WriteLine("Press any key to exit.");
         Console.ReadKey();
     }
 }
 // Output: Coords: 10,15

أعضاء جزئيون

يمكن أن تحتوي الفئة الجزئية على عضو جزئي. يحتوي جزء واحد من الفئة على توقيع العضو. يمكن تعريف التنفيذ في نفس الجزء أو في جزء آخر.

التطبيق غير مطلوب لأسلوب جزئي عندما يمتثل التوقيع للقواعد التالية:

  • لا يتضمن الإعلان أي معدلات وصول. يتمتع الأسلوب بوصول خاص بشكل افتراضي.

  • نوع الإرجاع void.

  • لا تحتوي أي من المعلمات على معدل out.

  • لا يمكن أن يتضمن تعريف الأسلوب أيا من المعدلات التالية:

    • ظاهري
    • تجاوز
    • سدود
    • الجديد
    • extern

تتم إزالة الأسلوب وجميع الاستدعاءات إلى الأسلوب في وقت التحويل البرمجي عندما لا يكون هناك تنفيذ.

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

بدءا من C# 13، يمكن للإعلان المنفذ لخاصية جزئية استخدام خصائص الحقل المدعومة لتعريف الإعلان المنفذ. توفر الخاصية المدعومة بالحقل بناء جملة موجزا حيث تصل الكلمة الأساسية للحقل إلى حقل النسخ الاحتياطي المجمع للمحول البرمجي للخاصية. على سبيل المثال، يمكنك كتابة التعليمات البرمجية التالية:


// in file1.cs
public partial class PropertyBag
{
    // Defining declaration
    public partial int MyProperty { get; set; }
}

// In file2.cs
public partial class PropertyBag
{
    // Defining declaration
    public partial int MyProperty { get => field; set; }
}

يمكنك استخدام field إما في ملحق get أو set أو كليهما.

مهم

الكلمة الأساسية field هي ميزة معاينة في C# 13. يجب استخدام .NET 9 وتعيين عنصر <LangVersion> للمعاينة في ملف المشروع لاستخدام الكلمة الأساسية السياقية field.

يجب أن تكون حذرا باستخدام ميزة الكلمة الأساسية field في فئة تحتوي على حقل يسمى field. ظلال الكلمة الأساسية field الجديدة لحقل يسمى field في نطاق ملحق الخاصية. يمكنك إما تغيير اسم متغير الحقل، أو استخدام الرمز المميز @ للإشارة إلى معرف الحقل ك @field.

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

  • رمز القالب: يحتفظ القالب باسم الأسلوب والتوقيع بحيث يمكن للتعليمات البرمجية التي تم إنشاؤها استدعاء الأسلوب . تتبع هذه الأساليب القيود التي تمكن المطور من تحديد ما إذا كان سينفذ الأسلوب. إذا لم يتم تنفيذ الأسلوب، فسيزيل المحول البرمجي توقيع الأسلوب وجميع الاستدعاءات إلى الأسلوب. لا يكون لاستدعاءات الأسلوب، بما في ذلك أي نتائج قد تحدث من تقييم الوسيطات في المكالمات، أي تأثير في وقت التشغيل. لذلك، يمكن لأي تعليمة برمجية في الفئة الجزئية استخدام أسلوب جزئي بحرية، حتى إذا لم يتم توفير التنفيذ. لا ينتج عن أي أخطاء وقت التحويل البرمجي أو وقت التشغيل إذا تم استدعاء الأسلوب ولكن لم يتم تنفيذه.

  • مولدات المصدر: توفر مولدات المصدر تنفيذا للأعضاء. يمكن للمطور البشري إضافة إعلان العضو (غالبا مع السمات التي يقرأها منشئ المصدر). يمكن للمطور كتابة التعليمات البرمجية التي تستدعي هؤلاء الأعضاء. يعمل منشئ المصدر أثناء التحويل البرمجي ويوفر التنفيذ. في هذا السيناريو، غالبا ما لا يتم اتباع القيود المفروضة على الأعضاء الجزئيين التي قد لا يتم تنفيذها.

    
    // Definition in file1.cs
    partial void OnNameChanged();
    
    // Implementation in file2.cs
    partial void OnNameChanged()
    {
      // method body
    }
    
    
  • يجب أن تبدأ إعلانات الأعضاء الجزئية بالكلمة الأساسية السياقية الجزئية.

  • يجب أن تتطابق توقيعات الأعضاء الجزئية في كلا الجزأين من النوع الجزئي.

  • يمكن أن يكون للعضو الجزئي معدلات ثابتة وغير آمنة.

  • يمكن أن يكون العضو الجزئي عاما. يجب أن تكون القيود هي نفسها على تعريف وتنفيذ إعلان الأسلوب. لا يجب أن تكون أسماء المعلمات واكتب المعلمات هي نفسها في الإعلان المنفذ كما هو الحال في تعريف واحد.

  • يمكنك تعيين تفويض إلى أسلوب جزئي محدد ومنفذ، ولكن ليس إلى أسلوب جزئي لا يحتوي على تنفيذ.