الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

نصائح وتوجيهات للبرمجة في C# (الحلقة 3) استعمال الproperties بدلاً من متغيرات public

بدأه عبد العظيم بخاري في 9 يناير 2011 · 3 رد · 1,108 مشاهدة · في Microsoft Visual C#.NET
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

تعتبر الproperties احدى مميزات لغة C# الرائعة والتي تطورت باستمرار منذ الإصدار الاول للغة , فيمكنك الان وضع معايير وصول على الget والset بكل سهولة . ومع التطور الذي حصل للproperties في C# 3.0 اصبحت كمية الأكواد اللازمة لعمل properties اقل بكثير من السابق وبشكل مشابه تقريباً لانشاء ايdata member.

فإذا كنت تستعمل متغيرات public في كلاساتك وانواعك فعليك بالتوقف فوراً َ. واذا كنت تستعمل الطريقة القديمة لانشاءالproperties (وذلك عبر انشاء set وget بشكل يدوي) فعليك بالتوقف ايضاً ! .(مالم تضع اي عملية منطقية فيهم).

عليك الان مواكبة التطور عبر استعمال الطريقة الأحدث لكتابة الproperties والتي هي مشابهة للdata members بينما هي في جوهرها عبارة عن نوع خاص من الmethods .

اذاً فالوصول للproperties هو مشابه للوصول لأي متغير public في النوع لكن الimplementation الحقيقي لها هو امر مشابه للmethods.

يفضل دائماً استعمال الproperties في اطار عمل الدوت نت بدلاً من public data members حيث أن جميع كلاسات الdata binding في الدوت نت مبنية بالاساس على الproperties وليس على متغيرات public , وهذا ينطبق على جميع مكتبات WPF و Windows Forms و Web Forms و SilverLight.

ملاحظة : تستعمل الية data bindings تقنية الreflection لايجاد property معينة في نوع ما .

textBoxCity.DataBindings.Add("Text",
address, "City");

يربط الكود السابق الproperty المسماة Text لكنترول textBoxCity بالproperty المسماة City للكائن address . فلو كان هذا الأمر مبني باستعمال متغير public اسمه City فلن ينجح . وذلك لأن مصممي مكتبات الدوت نت لم يدعموا هذا الأمر . لذلك يعتبر استعمال متغيرات public من الممارسات البرمجية السيئة في C# ولهذا لم يتم اضافة الدعم لهم لعمل مثل الكود السابق. ولاجل هذا عليك باستعمال تقنيات البرمجة الكائنية الصحيحة عن طريق الproperties في كوداتك.

اذاً فالdata binding يمكن تطبيقه فقط على تلك الكلاسات والأنواع التي تدعم properties .

يمكنك وضع بعض جمل التحكم في الproperties مما يجعلها سهلة التعديل لدرجة كبيرة . فلو افترضنا أن نوع Customer يجب أن لا يحتوي على اسم فارغ فيمكننا معالجة الأمر كالتالي :

public class Customer
{
private string name;
public string Name
{
get { return name; }
set
{
if (string.IsNullOrEmpty(value))
throw new ArgumentException(
"Name cannot be blank",
"Name");
name = value;
}
// باقي الكلاس.
}
}

اما لو كانت Name في الكود السابق هي متغير public فعليك أن تبحث في كل سطر في برنامجك حتى تضع جملة شرطية تمنع ادخال قيمة فارغة في ذلك المتغير. فمن اسرع واسهل برأيك ؟

من مميزات الproperties ايضاً أنها تطبق كنوع خاص من الmethods مما يجعل دعمها للmultithreaded اسهل بكثير , فيمكنك اضافة ميزة الوصول المتزامن للبيانات لكل من get وset كالاتي:

public class Customer
{
private object syncHandle = new object();
private string name;
public string Name
{
get
{
lock (syncHandle)
return name;
}
set
{
if (string.IsNullOrEmpty(value))
throw new ArgumentException(
"Name cannot be blank",
"Name");
lock (syncHandle)
name = value;
}
}
// باقي الكلاس.
}

تمتلك الproperties جميع مميزات وخصائص الmethods فيمكننا على سبيل المثال جعلها virtual كالاتي:

public class Customer
{
public virtual string Name
{
get;
set;
}
}

لاحظ أننا استعملنا النسخة المختصرة من الproperties في المثال الأخير والتي يمكن استخدامها في C# 3.0 فما فوق حيث أن هذه الطريقة تسهل علينا كثيراً عملية انشاء الproperties . لكن اذا احتجنا لوضع اي كود اضافي في الget أو الset مثل جمل التحكم وغيرها فعلينا استعمال النسخة العادية المطولة من الproperties.

يمكنك جعل الproperties من نوع abstract وتعرضها كجزء من نتعريف الانترفيس باستعمال نفس النمط الكتابي للطريقة المختصرة من الproperties.

يوضح المثال التالي تعريفproperty في انترفيس يأخذ generic .

public interface INameValuePair<T>
{
string Name
{
get;
}
T Value
{
get;
set;
}
}

لاحظ أنه على الرغم من أن الكود الخاص بالproperties هو بالنسخة المختصرة إلا أنه لا يتم عمل أي implementation لها في الإنترفيس من قبل الكومبايلر . فهي تحتوي على نمط يجب الإلتزام به اثناء عمل implement لذلك الإنترفيس .

نعود ونذكر بأن الproperties تمثل بيانات داخلية للكلاس أو النوع فيمكنك باستعمالها الوصول لتلك البيانات وتعديلها . حيث أن أي شيئ يمكنك عمله مع متغيرات public يمكنك عمله نفس الشيئ مع الproperties.

يمكنك وضع معياران وصول مختلفان في property ما من اجل قراءة البيانات ووضعها , وهذا الأمر يعطينا تحكم عظيم بمقدار ظهور عناصر البيانات كproperties.

public class Customer
{
public virtual string Name
{
get;
protected set;
}
// باقي الكلاس.
}

في حال كان النوع الخاص بك يحتوي على عناصر مفهرسة فيمكنك استعمال الindexers والتي هي عبارة عن properties لكن تمتلك باراميترز . وهذا الأمر مفيد لانشاء property تقوم بارجاع عناصر بترتيب معين .

public int this[int index]
{
get { return theValues[index]; }
set { theValues[index] = value; }
}
// الوصول للاندكسر
int val = someObject;

تمتلك الindexers جميع مميزات الproperties العادية , فيمكنك وضع اي حسابات أو فحوصات للقيم اخل الindexer ويمكنك ايضاً جعل الindexers من نوع virtual أو abstract ويمكن وضعها في الinterfaces .و يمكنك ايضاً جعلها قابلة للقراءة فقط أو الكتابة فقط .

يمكننا استعمال الindexer ذو البعد الواحد والذي له باراميتر رقمي صحيح في الdate binding بينما يتم استعمال الindexers الاخرى التي تمتلك باراميترز ليست رقمية صحيحة في تعريف الmaps والdictionaries.

public Address this[string name]
{
get { return adressValues[name]; }
set { adressValues[name] = value; }
}

يمكنك انشاء indexers متعددة الأبعاد (بشكل متوافق مع الarrays متعددة الأبعاد) بأنواع مختلفة أو متشابهة على كل بعد . لاحظ الكود التالي:

public int this[int x, int y]
{
get { return ComputeValue(x, y); }
}
public int this[int x, string name]
{
get { return ComputeValue(x, name); }
}

لاحظ أنه يتم تعريف جميع الindexers في C# بالكلمة المحجوزة this فلا يمكنك اعطاءها اسم ما , لذلك يجب لكل indexer يختلف بالنوع بأن يمثل بوضع قائمة مختلفة من الباراميترز حتى لا يحصل هناك اي تعارض .

لاحظ أن الindexers تمتلك جميع مميزات الproperties فيمكنك عملها virtual أو abstract ويمكنك عمل معيار وصول مختلف لكل من set و get . لكن لا يمكنك انشاء نسخة مختصرة من الindexers كما هو الحال مع الproperties.

قد يقول أحد المطورين ماذا لو وضعت متغيرات public ثم بعد أن انتهي من الكود سوف اقوم بتغييرها ووضع properties بدلاً منها .

فمع أن هذا الأمر يبدو مقبولاً لكنه خاطئ.

انظر للمثال التالي:

// استعمال متغيرات (ممارسة سيئة)
public class Customer
{
public string Name;
// باقي الكلاس.
}

يمثل هذا الكود زبون معين مع اسم , فيمكننا قراءة هذا الإسم وتعديله باستعمال النمط الإعتيادي .

string name = customerOne.Name;
customerOne.Name = "Abed";

هذه الطريقة بسيطة وصحيحة وقد تعتقد أن تبديل متغيرات الpublic في الكلاس ووضع properties بدلاً منها لن يؤثر على الكود وسيبقى يعمل بدون اي تعديل .

هذا الأمر صحيح نوعاً ما حيث أن التعامل مع الproperties هو نفس التعامل مع الdata members . لكن في الواقع فالproperties ليست data حيث أن الوصول لproperty يولد كود Microsoft Intermediate Language (MSIL) يختلف عن الوصول لمتغير public.

فعلى الرغم من أن الproperties والdata members يهدفان لتغير المصدر نفسه من البيانات حيث أنه يوجد توافق مصدري بينهما لكن لا يوجد في الواقع توافق binary فيما بينهم .

ففي الحالة السابقة عندما يتم تغير متغير الpublic لproperty مكافئة فيجب عليك اعادة ترجمة جميع الكودات التي تستعمل متغير الpublic هذا والذي يعني أن عمل ترقية لمكتبات الassemblies اكثر صعوبة وهذا ما تحاول لغة C# تجنبه حيث أن هدفها هو انشاء اسمبلي منفردة محدثة للبرنامج دون ترقية التطبيق.

عند القاء نظرة على الIL لproperty ما فإنك ستتسائل عن الفارق في اداء الproperty عن الdata members . فالproperty لن تكون اسرع بالوصول من المتغيرات public لكن لن تكون ايضاً ابطأ !

حيث يقوم الكومبايلر JIT بعمل inline للproperty assessors مما يجعل اداءها مشابه لاداء الdata members . فلو لم يقم الكومبايلر بذلك فستزداد تكلفة الأداء للproperty عن المتغير "باستدعاء لفنكشن" وهو فرق بسيط للغاية يمكن اهماله باستثناء بعض الحالات التي يكون فيها عبارة عن فارق صغير.

فملخص كلامنا هذا هو أن الproperties عبارة عن methods تبدو من الخارج كمتغيرات للبيانات واستعمالها بدلاً من متغيرات public يوفر عليك الكثير من الوقت والجهد ويعطيك الكثير من المميزات وعلى رأسها data binding.

يمكنك مراجعة الدرس التالي حتى تفرق بين الproperty والميثود :

اضغط هنا

عبد العظيم بخاري

http://www.el-bukhari.com/2011/01/c-3-properties-public.html

#2

السلام عليكم

مشكور جدا على هذا المقال

وبجد فيه حاجات جامدة مش كنت عارفها

وانا من محبي ومفضلي التعامل عن طريق الــ Properties

بس كان عندي طلب عاوز اعرفه كيفية تنفيذه مع الشرح طبعا

دلوقتي انا بعمل كنترول

عاوز اعمل Property زي اللي في الصورة دي

انها تكون فيها زر استعراض

post-73411-018975200 1294923059_thumb.pn

وعند الضغط على الزر المبين

عند الضغط على الزر المبين تظهر الفورمة التالية

post-73411-017348800 1294923323_thumb.pn

طبعا النموذج ده بتاع الدوت نت مش بتاعي

لكن اللي عاوز اعمله

فورمة فيها جردة اسجل فيها بعض القيم

هل فهمت قصدي ؟

المرفقات
btn1.pngbtn2.png

Mohamed Ali Salim

0.1..0...4....7.....6......2.......7........4.........8

#3

السلام عليكم

يمكنك عمل ذلك اخي الكريم عن طريق الReflection و كنترول property grid

راجع الروابط التالية

http://msdn.microsoft.com/en-us/library/aa302334.aspx

http://msdn.microsoft.com/en-us/library/aa302326.aspx

http://en.csharp-online.net/Design-Time_Integration%E2%80%94Property_Browser_Integration

#4

شكراااااا وجاري القراءة...

Mohamed Ali Salim

0.1..0...4....7.....6......2.......7........4.........8

مواضيع مشابهة

عدد الزوار حالياً

المتواجدون خلال آخر دقيقتين · يتحدّث كل ٣٠ ثانية

—الإجمالي—أعضاء مسجّلون—زوار بدون تسجيل

جارٍ التحقق من المتواجدين…