بدء استخدام خصائص الفئة والملحقات
توفر خصائص الفئة آلية مرنة لقراءة قيمة حقل بيانات أو كتابتها أو حسابها. تظهر كأعضاء بيانات عامة، ولكن يتم تنفيذها كأساليب خاصة تسمى الملحقات. تمكن هذه الميزة المتصلين من الوصول إلى البيانات بسهولة ولا تزال تساعد في تعزيز أمان البيانات ومرونتها.
استخدام الخصائص
تجمع الخصائص بين جوانب كل من الحقول والأساليب. لمستخدم كائن، تظهر الخاصية ك حقل. يتطلب الوصول إلى الخاصية نفس بناء الجملة مثل الوصول إلى حقل. إلى منفذ فئة ما، الخاصية هي كتلة واحدة أو كتلتين من التعليمات البرمجية، تمثل ملحق get و/أو set أو موصل init. يتم تنفيذ كتلة التعليمات البرمجية لملحق get عند قراءة الخاصية. يتم تنفيذ كتلة التعليمات البرمجية set أو ملحق init عند تعيين قيمة للخاصية. تعتبر الخاصية التي لا تحتوي على ملحق set للقراءة فقط. تعتبر الخاصية التي لا تحتوي على ملحق get خاصية للكتابة فقط. الخاصية التي تحتوي على كلا الملحقين هي القراءة والكتابة. يمكنك استخدام موصل init بدلا من ملحق set لتمكين تعيين الخاصية كجزء من تهيئة الكائن ولكن بخلاف ذلك جعله للقراءة فقط.
على عكس الحقول، لا يتم تصنيف الخصائص كمتغيرات. لذلك، لا يمكنك تمرير خاصية كمعلمة ref أو out.
غالبا ما تستخدم الخصائص لدعم السيناريوهات التالية:
- يمكنهم التحقق من صحة البيانات قبل السماح بإجراء تغيير.
- يمكنهم عرض البيانات بشفافية على فئة حيث يتم استرداد تلك البيانات من مصدر آخر، مثل قاعدة بيانات.
- يمكنهم اتخاذ إجراء عند تغيير البيانات، مثل رفع حدث أو تغيير قيمة الحقول الأخرى.
يتم تعريف الخصائص في كتلة التعليمات البرمجية لتعريف فئة. يتم تعريف الخصائص عن طريق تحديد مستوى الوصول للحقل، متبوعا بنوع الخاصية، متبوعا باسم الخاصية، متبوعا بكتلة تعليمات برمجية تعلن عن ملحق get و/أو ملحق set.
ملحق get
يشبه نص ملحق get نص الأسلوب. يجب أن ترجع قيمة من نوع الخاصية. يكتشف المحول البرمجي C# والمحول البرمجي في الوقت المناسب (JIT) الأنماط الشائعة لتنفيذ ملحق get، وتحسين هذه الأنماط.
على سبيل المثال، من المحتمل أن يتم تحسين ملحق get الذي يقوم بإرجاع حقل دون إجراء أي حساب لقراءة ذاكرة هذا الحقل. الخصائص المنفذة تلقائيا، التي تم فحصها في الوحدة التالية من هذه الوحدة النمطية، اتبع هذا النمط والاستفادة من هذه التحسينات. ومع ذلك، لا يمكن تحليل أسلوب ملحق get الظاهري لأن المحول البرمجي لا يعرف في وقت التحويل البرمجي الطريقة التي قد يتم استدعاؤها بالفعل في وقت التشغيل.
يوضح المثال التالي موصل get يرجع قيمة حقل خاص _name:
public class Employee
{
private string _name = "unknown"; // the name field
public string Name
{
get { return _name; } // the Name property
}
}
في هذا المثال، تتضمن فئة Employee حقلا خاصا وخاصية عامة. فيما يلي شرح لتعريف فئة Employee:
- يتم تعريف فئة
Employeeمع معدل الوصول العام، ما يعني أنه يمكن الوصول إليها من أي تعليمة برمجية أخرى في نفس التجميع أو تجميع آخر يشير إليه. - يتم تعريف
_nameالحقل الخاص بنوعstringويتم تعيين قيمة افتراضية له،"unknown". - يتم تعريف
Nameالخاصية العامة بنوعstring. تتضمن الخاصية ملحقgetالذي يرجع قيمة حقل_name.
ملاحظه
غالبا ما تسمى الحقول التي توفر قيم ملحقات الخصائص حقول دعم.
خذ دقيقة للنظر في التعليمات البرمجية التي تنشئ مثيلا لكائن Employee وتقرأ قيمة الخاصية Name:
Employee employee = new Employee(); // create an instance of the Employee class
Console.Write(employee.Name); // use the get accessor to read the value of the Name property
ينشئ نموذج التعليمات البرمجية هذا مثيلا لكائن Employee جديد يسمى employee. عندما تشير التعليمات البرمجية إلى خاصية employee.Name، باستثناء كهدف للتعيين، يتم استدعاء ملحق get لقراءة قيمة الخاصية. في هذه الحالة، يقوم ملحق get بإرجاع قيمة حقل _name، الذي تم تعيين القيمة "unknown".
يمكن أيضا استخدام كتلة التعليمات البرمجية لملحق get لإرجاع قيمة محسوبة. يمكن أن يكون هذا مفيدا عندما تريد التأكد من أن الخاصية ترجع دائما قيمة غير فارغة. على سبيل المثال:
public class Manager
{
private string? _name;
public string Name
{
get
{
return _name != null ? _name : "NA";
}
}
}
ملحق set
يشبه ملحق set أسلوبا يكون نوع الإرجاع فيه فارغا. يستخدم معلمة ضمنية تسمى value، ونوعها هو نوع الخاصية . يتعرف المحول البرمجي والمحول البرمجي JIT أيضا على الأنماط الشائعة لملحق set أو init. يتم تحسين هذه الأنماط الشائعة، وكتابة الذاكرة مباشرة لحقل النسخ الاحتياطي. في المثال التالي، تتم إضافة ملحق set إلى خاصية Name:
class Student
{
private string? _name; // the name field
public string Name // the Name property
{
get
{
return _name != null ? _name : "NA";
}
set
{
_name = value;
}
}
}
خذ دقيقة للنظر في التعليمات البرمجية التي تنشئ مثيلا لفئة Student. عند تعيين قيمة للخاصية Name، يتم استدعاء ملحق set باستخدام وسيطة توفر القيمة الجديدة. على سبيل المثال:
var student = new Student();
student.Name = "StudentName"; // the set accessor is invoked here
Console.Write(student.Name); // the get accessor is invoked here
ملحق init
التعليمات البرمجية لإنشاء ملحق init هي نفس التعليمات البرمجية لإنشاء ملحق set باستثناء أنك تستخدم الكلمة الأساسية init بدلا من set. الفرق هو أنه لا يمكن استخدام ملحق init إلا في الدالة الإنشائية أو باستخدام تهيئة كائن.
الإعلان عن خصائص القراءة والكتابة واستخدامها
توفر الخصائص راحة أعضاء البيانات العامة دون المخاطر التي تأتي مع الوصول غير المحمي وغير الخاضع للرقابة وغير المدقق إلى بيانات العنصر. تعلن الخصائص عن الملحقات: أساليب خاصة تقوم بتعيين القيم واستردادها من عضو البيانات الأساسي. يتيح ملحق set تعيين أعضاء البيانات، ويسترد ملحق get قيم أعضاء البيانات.
تعرض هذه العينة فئة Person لها خاصيتان: Name (سلسلة) Age (int). توفر كلتا الخاصيتين get وملحقات set، لذلك تعتبر خصائص القراءة/الكتابة.
class Person
{
private string _name = "N/A";
private int _age = 0;
// Declare a Name property of type string:
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
// Declare an Age property of type int:
public int Age
{
get
{
return _age;
}
set
{
_age = value;
}
}
}
class TestPerson
{
static void Main()
{
// Create a new Person object named person:
Person person = new Person();
// Print out the default name and age of the person:
Console.WriteLine($"Person details - Name = {person.Name}, Age = {person.Age}");
// Set some values on the person object:
person.Name = "PersonName";
person.Age = 99;
Console.WriteLine($"Person details - Name = {person.Name}, Age = {person.Age}");
// Increment the Age property:
person.Age += 1;
Console.WriteLine($"Person details - Name = {person.Name}, Age = {person.Age}");
// Keep the console window open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
/* Output:
Person details - Name = N/A, Age = 0
Person details - Name = PersonName, Age = 99
Person details - Name = PersonName, Age = 100
*/
بناء جملة الملحق وتقنيات الترميز
بالإضافة إلى بناء الجملة الأساسي للإعلان عن الخصائص، يتضمن C# بناء الجملة الذي يمكنك من كتابة تعليمات برمجية أكثر إيجازا وتعبيرا. تتضمن هذه الميزات ما يلي:
- الأعضاء الذين يتمتعون بجسد التعبير
- الخصائص المدعومة بالحقل
- الخصائص المطلوبة
الأعضاء الذين يتمتعون بجسد التعبير
يوفر أعضاء التعبير الجسم بناء جملة أكثر إيجازا لكتابة ملحقات خاصية سطر واحد.
ملاحظه
يمكن أيضا تطبيق أعضاء التعبير الجسم على الأساليب والمفهرسات وملحقات الحدث.
غالبا ما تتكون ملحقات الخصائص من عبارات سطر واحد تقوم بتعيين نتيجة تعبير أو إرجاعها. تعد فئة Person التي فحصتها سابقا في هذه الوحدة مثالا جيدا:
class Student
{
private string? _name; // the name field
public string Name // the Name property
{
get
{
return _name != null ? _name : "NA";
}
set
{
_name = value;
}
}
}
في هذا المثال، تستخدم الخاصية Name عبارة سطر واحد لإرجاع قيمة الحقل _name إذا لم تكن خالية، أو السلسلة "NA" إذا كانت خالية. يستخدم ملحق set عبارة سطر واحد لتعيين قيمة الخاصية Name إلى حقل _name.
يتكون تعريف نص التعبير من الرمز المميز => متبوعا بالتعبير المستخدم لتعيين قيمة الخاصية أو استردادها. نظرا لأن الملحقات المعرفة لفئة Student تنفذ عبارة من سطر واحد، فهي مرشح جيد للتحديث باستخدام تعريفات نص التعبير.
تقوم القصاصة البرمجية التالية بتحديث فئة Student باستخدام تعريفات نص التعبير get وملحقات set:
class Student
{
private string? _name; // the name field
public string Name // the Name property
{
get => _name ?? "NA";
set => _name = value;
}
}
خصائص الحقل المدعومة
بدءا من C# 13، يمكنك إضافة التحقق من الصحة أو منطق آخر في الملحق لخاصية باستخدام ميزة معاينة الكلمة الأساسية field. تصل الكلمة الأساسية field إلى حقل النسخ الاحتياطي المجمع للمحول البرمجي لخاصية. يمكنك من كتابة ملحق خاصية دون الإعلان صراحة عن حقل دعم منفصل.
public class Person
{
public string? FirstName
{
get;
set => field = value.Trim();
}
// Omitted for brevity.
}
مهم
الكلمة الأساسية field هي ميزة معاينة في C# 13. يجب استخدام .NET 9 وتعيين عنصر <LangVersion> للمعاينة في ملف المشروع لاستخدام الكلمة الأساسية السياقية field.
يجب أن تكون حذرا باستخدام ميزة الكلمة الأساسية field في فئة تحتوي على حقل يسمى field. ظلال الكلمة الأساسية field الجديدة لحقل يسمى field في نطاق ملحق الخاصية. يمكنك إما تغيير اسم متغير field، أو استخدام الرمز المميز @ للإشارة إلى معرف الحقل ك @field.
الخصائص المطلوبة
يسمح المثال السابق للمتصل بإنشاء Person باستخدام الدالة الإنشائية الافتراضية، دون تعيين الخاصية FirstName. يتم تعيين نوع الخاصية إلى سلسلة تقبل القيم الخالية. بدءا من C# 11، يمكنك مطالبة المتصلين بتعيين خاصية:
public class Person
{
public Person() { }
[SetsRequiredMembers]
public Person(string firstName) => FirstName = firstName;
public required string FirstName { get; init; }
// Omitted for brevity.
}
تقوم التعليمات البرمجية السابقة بإجراء تغييرين على فئة Person. أولا، يتضمن إعلان خاصية FirstName معدل required. وهذا يعني أن أي تعليمة برمجية تنشئ Person جديدة يجب تعيين هذه الخاصية باستخدام تهيئة كائن. ثانيا، الدالة الإنشائية التي تأخذ معلمة firstName لها السمة System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute. تعلم هذه السمة المحول البرمجي أن هذا المنشئ يعين كافة الأعضاء المطلوبين. لا يطلب من المتصلين الذين يستخدمون الدالة الإنشائية هذه تعيين خصائص required مع تهيئة كائن.
مهم
لا تخلط بين required وغير القيم الخالية. من الصالح تعيين خاصية required إلى null أو default. إذا كان النوع غير يقبل القيم الخالية، مثل string في هذه الأمثلة، يصدر المحول البرمجي تحذيرا.
var aPerson = new Person("PersonName");
aPerson = new Person{ FirstName = "PersonName"};
// Error CS9035: Required member `Person.FirstName` must be set:
//aPerson2 = new Person();