Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

الحقول الخلفية (Backing Fields)

جزء من قسم Object Oriented Programming في رحلة C# على Coddy — الدرس 17 من 70.

تعد الخصائص المنفذة تلقائيًا مريحة، ولكنك تحتاج أحيانًا إلى مزيد من التحكم في كيفية تخزين الخاصية لقيمتها أو استرجاعها. وهنا يأتي دور الحقول الخلفية (backing fields). الحقل الخلفي هو حقل خاص يخزن البيانات الفعلية للخاصية.

public class Product
{
    private decimal _price;  // حقل خلفي
    
    public decimal Price
    {
        get { return _price; }
        set { _price = value; }
    }
}

يبدو هذا كعمل إضافي مقارنة بالخصائص التلقائية (auto-properties)، ولكن الحقول الداعمة (backing fields) تتيح لك إضافة منطق برمجِي. على سبيل المثال، يمكنك التحقق من صحة البيانات قبل تخزينها:

public class Product
{
    private decimal _price;
    
    public decimal Price
    {
        get => _price;
        set => _price = value < 0 ? 0 : value;
    }
}

الآن تصبح الأسعار السالبة صفراً تلقائياً. يمكنك أيضاً تحويل البيانات عند القراءة أو الكتابة، أو تسجيل التغييرات، أو تشغيل إجراءات أخرى.

تستخدم اصطلاحات تسمية الحقل الداعم عادةً بادئة بشرطة سفلية (_price) أو أحرفاً صغيرة (price) لتمييزه عن الخاصية.

عندما تستخدم الخصائص المنفذة تلقائيًا مثل public decimal Price { get; set; }، يقوم المترجم في الواقع بإنشاء حقل دعم مخفي لك. تمنحك حقول الدعم الصريحة نفس التخزين مع تحكم كامل في السلوك.

challenge icon

التحدي

سهل

دعونا نبني نظام مستشعر درجة حرارة يستخدم حقولاً خلفية (backing fields) للتحقق من البيانات وتحويلها أثناء تخزينها واسترجاعها.

ستقوم بإنشاء ملفين لتنظيم الكود الخاص بك:

  • TemperatureSensor.cs: قم بتعريف فئة TemperatureSensor داخل مساحة الأسماء Sensors. يقيس هذا المستشعر درجة الحرارة بالدرجة المئوية، ولكننا نحتاج إلى التأكد من بقاء القراءات ضمن حدود صالحة. استخدم الحقول الخلفية لتنفيذ ما يلي:
    • خاصية Location (سلسلة نصية) مع حقل خلفي _location. عند تعيين الموقع، إذا كانت القيمة فارغة أو null، قم بتخزين "Unknown" بدلاً من ذلك.
    • خاصية Temperature (double) مع حقل خلفي _temperature. عند تعيين درجة الحرارة، قم بحصر القيمة بين -50 و 150 (إذا كانت أقل من -50، خزن -50؛ وإذا كانت أعلى من 150، خزن 150).
    • خاصية للقراءة فقط TemperatureFahrenheit تقوم بحساب وإرجاع درجة الحرارة بالفهرنهايت باستخدام الصيغة: (celsius * 9 / 5) + 32. يجب أن تستخدم هذه الخاصية الحقل الخلفي مباشرة.
    • منشئ (constructor) يقبل قيم الموقع ودرجة الحرارة الأولية.
  • Program.cs: في ملفك الرئيسي، قم بإنشاء مستشعر باستخدام قيم الإدخال واعرض قراءاته. ثم قم بتحديث درجة الحرارة بقيمة إدخال ثانية واعرض القراءات المحدثة.

ستتلقى ثلاثة مدخلات:

  • موقع المستشعر
  • قراءة درجة الحرارة الأولية
  • قراءة درجة الحرارة المحدثة

اطبع المخرجات بهذا التنسيق:

Sensor: {Location}
Temperature: {Temperature}C ({TemperatureFahrenheit}F)
Updated Temperature: {Temperature}C ({TemperatureFahrenheit}F)

على سبيل المثال، إذا كانت المدخلات هي Lab Room و 25 و 200، يجب أن تكون المخرجات:

Sensor: Lab Room
Temperature: 25C (77F)
Updated Temperature: 150C (302F)

لاحظ كيف تم حصر القراءة الثانية 200 لتصبح 150 لأنها تتجاوز الحد الأقصى لدرجة الحرارة الصالحة. تمنحك الحقول الخلفية هذا التحكم في كيفية تخزين البيانات!

ورقة مرجعية

الـ backing field (الحقل الخلفي) هو حقل خاص (private field) يخزن البيانات الفعلية لخاصية ما، مما يسمح لك بإضافة منطق مخصص لجلب القيم وتعيينها.

الصيغة الأساسية للحقل الخلفي

public class Product
{
    private decimal _price;  // حقل خلفي
    
    public decimal Price
    {
        get { return _price; }
        set { _price = value; }
    }
}

صيغة التعبير المختصرة (Expression-Bodied Syntax)

public decimal Price
{
    get => _price;
    set => _price = value;
}

إضافة منطق التحقق من الصحة

تسمح لك الحقول الخلفية بالتحقق من صحة البيانات أو تحويلها قبل تخزينها:

private decimal _price;

public decimal Price
{
    get => _price;
    set => _price = value < 0 ? 0 : value;  // منع الأسعار السالبة
}

اصطلاح التسمية

عادةً ما تستخدم الحقول الخلفية بادئة بشرطة سفلية (_price) أو أحرفًا صغيرة (price) لتمييزها عن اسم الخاصية.

الخصائص التلقائية مقابل الحقول الخلفية

الخصائص المنفذة تلقائيًا مثل public decimal Price { get; set; } تنشئ تلقائيًا حقلاً خلفيًا مخفيًا. بينما تمنحك الحقول الخلفية الصريحة نفس التخزين مع تحكم كامل في السلوك.

جرّب بنفسك

using System;
using Sensors;

class Program
{
    public static void Main(string[] args)
    {
        // قراءة المدخلات
        string location = Console.ReadLine();
        double initialTemp = Convert.ToDouble(Console.ReadLine());
        double updatedTemp = Convert.ToDouble(Console.ReadLine());

        // TODO: إنشاء TemperatureSensor مع الموقع ودرجة الحرارة الأولية

        // TODO: طباعة موقع المستشعر وقراءات درجة الحرارة الأولية
        // التنسيق: "Sensor: {Location}"
        // التنسيق: "Temperature: {Temperature}C ({TemperatureFahrenheit}F)"

        // TODO: تحديث درجة حرارة المستشعر بالقيمة المحدثة

        // TODO: طباعة قراءات درجة الحرارة المحدثة
        // التنسيق: "Updated Temperature: {Temperature}C ({TemperatureFahrenheit}F)"
    }
}
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس Object Oriented Programming