متى تستخدم الـ Sturct
بالنسبة لي اعتبر الـ Struct مجرد حاوية لبعض القيم من صنف واحد ، لا اكثر
مثال 1 :
نعرف ان الفضاء الثلاثي الابعاد لديه 3 محاور :
اذن لو اردنا وصف نقطة في هذا المجال في برنامجنا وعرضها على الشاشة مقلا ، نستطيع عمل 3 متغيرات عادية بهذا الشكل :
PHP كود :
int x = 2;
int y = 3;
int z = 4;
MessageBox.Show(x.ToString() + y.ToString() + z.ToString());
لكن بالطبع هذه الطريقة تافهة جدا لتوصيف النقاط ، حيث انك ستعرف 3 متغيرات لكل نقطة !!! شيئ متعب جدا
قد يقول البعض سأستعمل المصفوفات ، ولكن المصفوفات مجرد حل فاشل هو الاخر لانها لم تخصص للتعامل مع هذا الاسلوب.
الحل المثالي ، استعمال
انشاء struct :
PHP كود :
struct Vector3D
{
public int x, y, z;
public Vector3D(int x, int y, int z)
{
this.x = x;
this.y = y;
this.z = z;
}
}
الان يمكننا وصف النقطة وعرضها بدون عمل متغيرات :
PHP كود :
Vector3D vector = new Vector3D(2, 3, 4);
MessageBox.Show(vector.x.ToString() + vector.y.ToString() + vector.z.ToString());
اذن كما تلاحظ جمعنا قيم من نفس الصنف في Type واحد وهذه فائدة عظيمة ، هل هذا كل شيئ ؟؟؟؟ لا ...
انظر لهذا السطر كم هو قبيح :
PHP كود :
MessageBox.Show(vector.x.ToString() + vector.y.ToString() + vector.z.ToString());
هل يمكننا عمل امر بخصوص هذا الموضوع ، نعم يمكنك عمل override للدالة ToString وتجعلها كالتالي مثلا :-
PHP كود :
struct Vector3D
{
public int x, y, z;
public Vector3D(int x, int y, int z)
{
this.x = x;
this.y = y;
this.z = z;
}
public override string ToString()
{
return "x:" + x + " y:" + y + " z:" + z;
}
}
الان عند العرض :-
PHP كود :
Vector3D vector = new Vector3D(2, 3, 4);
MessageBox.Show(vector.ToString()); //x:2 y:3 z:4
كم هذا مريح ، وهل هذا كل شيئ ، لاااا
تستطيع اضافة عمليات تختص بالVector داخل الstruct
مثلا عملية جمع كائنين من 2 vectors
PHP كود :
struct Vector3D
{
public int x, y, z;
public Vector3D(int x, int y, int z)
{
this.x = x;
this.y = y;
this.z = z;
}
public override string ToString()
{
return "x:" + x + " y:" + y + " z:" + z;
}
public static Vector3D operator+ (Vector3D a , Vector3D b)
{
return new Vector3D(a.x + b.x, a.y + b.y, a.z + b.z);
}
}
يمكننا ايضا اضافة احدى العمليات الحسابية التي تتعلق بالVectors مثلا حساب الـ Magnitude :
PHP كود :
public static Vector3D operator+ (Vector3D a , Vector3D b)
{
return new Vector3D(a.x + b.x, a.y + b.y, a.z + b.z);
}
public double Magnitude
{
get { return Math.Sqrt(Math.Pow(x, 2) + Math.Pow(y, 2) + Math.Pow(z, 2)); }
}
وفي النهاية :
PHP كود :
Vector3D vector = new Vector3D(2, 3, 4);
Vector3D vector2 = new Vector3D(33, 2, 13);
Vector3D finalVector = vector + vector2; //جمع الفيكتور
MessageBox.Show(finalVector.Magnitude.ToString()); //عرض الماغنيود
----
مثل ماتلاحظ قمنا بعمل Type احترافي للـ Vector من الـ Struct
طبعا هذا لايعني انه لايمكننا عمله باستعمال الـ Class ولكن الطريقة الامثل اكيد باستعمال الـ Struct
اساسا لو استعملنا الـ Class بتواجهنا الطامة الكبرى بخصوص عملية الـ Assignment وذلك بسبب ان الـ Class هو Reference Type
هل تريد ان تعرف المشكلة التي ستحصل لو استعملنا الـ Class ؟؟؟
بافتراض حولنا الstruct الذي انشاناه الى class :
ثم حاولنا كتابة التالي :
PHP كود :
Vector3D vector = new Vector3D(2, 3, 4);
Vector3D vector2 = vector;
vector.x = 120200;
vector.y = 323232;
vector.z = 343511;
MessageBox.Show(vector2.ToString()); //120200 , 323232, 343511
MessageBox.Show(vector.ToString()); //120200 , 323232, 343511
الرسالتين اعلاه سيطبعان نفس النتيجة !!!!!!!!!!!!!!!!!!!!
يالها من فاجعة .... كيف ذلك !!
فكما نلاحظ لم يتم العبث في قيمة الكائن vector2 ، بل تم التعديل على الكائن vector
اذن مادخل الكائن المسكين vector2 في الموضوع . هل فقط لانه استعار القيمة الابتداية من الكائن vector !!! ياللظلم
نعم هذه طبيعة عمل الClass ، فهو كالـ Pointers ..
مما يعني انه اي تعديل على احد الكائئنات التي تم عمل Assignment لها ، راح يغير على الكائنات الاخرى .
فالان لو فقط ارجعنا الـ class الى struct
لن تكون هناك المشكلة التي ناقشناها بالاعلى ، فكل كائن يشير الى نفسه
PHP كود :
Vector3D vector = new Vector3D(2, 3, 4);
Vector3D vector2 = vector;
vector.x = 10;
vector.y = 30;
vector.z = 50;
MessageBox.Show(vector.ToString()); //10 , 30, 50
MessageBox.Show(vector2.ToString()); //2 , 3, 4
هذا هو الفرق التقني الكبير بين الـ Struct وبين الـ Class
--
وكما قلت سابقا ، نستعمل الـ Sturct عندما تكون لدينا عدة قيم بسيطة من نفس الصنف
مثلا الـ Time يحتوي على ساعة ودقائق وثواني ، لذلك نعرفه
Struct
مثلا الـ Size يحتوي على محور سيني ومحور صادي ، لذلك نعرفه
Struct
مثلا الـ Address يحتوي على عدة ارقام او نصوص، لذلك نعرفه
Struct
مثلا الـ Range يحتوي على رقم بداية ونهاية، لذلك نعرفه
[b]Struct[/b]
مثلا المستطيل (Rectangle) يحتوي على 4 قيم من نفس النوع ، يمكننا تعريفه كـ
Struct
وفي نفس الوقت يمكننا تعريف الـ Rectangle مثلا كـ Class في حالة كان الاستخدام معقدا
مثلا لو عرفنا الـ Rectangle كـ Struct ثم اضفنا فيه اكواد لعمليات الرسم بالGDI والطباعة وغيرها من الامور التي تتعامل مع Unmanaged Resources
اعتقد تصبح مشكلة وقد يحصل كراش ايضا ، لذلك اي Type تريد استخدامه كـ (سلاح ثقيل) استعمل الـ Class
اما (الاسلحة الخفيفة) مثل العمليات الحسابية والتحويلات وغيره استعمل الـ Struct
واهم شيئ ، لاتنسى موضوع الـ Value Type الذي وضحته بالاعلى
تحياتي