المصفوفات Arrays في C#
ماهي المصفوفات Arrays في البرمجة..؟!! وكيف يتم تعريف المصفوفات Arrays في لغة سي شارب ....؟!! وما أنواع المصفوفات Arrays في سي شارب..؟؟ وكيف تمرر المصفوفة Array عبر الدوال Methods..؟!!
يعتبر التعامل مع القوائم أو المصفوفات جزء أساسي لتعلم أي لغة برمجة مع اختلاف وتعدد أنواع القوائم من لغة برمجة إلى اخرى. في هذا المقال سنتكلم عن المصفوفات Arrays في لغة سي شارب سنتعرف على طريقة إنشاء المصفوفة Array والتعامل معها من خلال تعليمات لغة C#لنبدأ...
في هذا المقال نتعرف على :
- المصفوفات ِArrays في البرمجة.
- المصفوفات ِArrays في لغة C#.
- المصفوفة الخطية Linear Array.
- تعليمة foreach و المصفوفات Arrays في C#
- المصفوفة Array والدوال Methods.
المصفوفات Arrays في البرمجة
المصفوفات Arrays هي نوع من هياكل البيانات وتدعم أغلب لغات البرمجة استخدام المصفوفات Arrays. والمصفوفة Array هي مجموعة من العناصر المرتبة المترابطة مع بعضها البعض. وقد تتعدد أنواع المصفوفات Arrays وتتخلف من لغة برمجة إلى أخرى فمثلاً في لغة Python نجد القوائم Lists كمثال للمصفوفات Arrays و في لغة C# لدينا المصفوفات Arrays.
قد تحتوي المصفوفة Array على عناصر من نوع بيانات واحد أو متعددة الأنواع فالقائمة List في بايثون تسمح بتنوع الأنواع لعناصر القائمة أما في لغة سي شارب عناصر المصفوفة Array لابد أن تكون من نفس النوع . وبما أن المصفوفة تتمثل نوع من أنواع هياكل البيانات Data Structure سيتم التعامل معها برمجياً معاملة الـ Object لها خصائصها ودوالها Properties and Methods.
المصفوفات في لغة C#
المصفوفات Arrays في لغة سي شارب ( C#) هي نوع من هياكل بيانات تسمح للمطورين بتخزين وتنظيم مجموعة من القيم ذات نفس النوع في مكان واحد. و تُستخدم المصفوفات Arrays بشكل شائع لتخزين مجموعة من العناصر مثل الأعداد أو النصوص أو أي نوع آخر من البيانات.
ويمكن تعريف المصفوفة Array في لغة C# انها نوع الـ Data Structure الذي يمثل مجموعة عناصر (Elements) مفهرسة و مترابطة مع بعضها البعض ولها نفس نوع البيانات. و المصفوفة Array في سي شارب يمكن أن تكون خطية أو غير خطية حيث تدعم سي شارب أشكال متعددة من المصفوفات Arrays مثل:
- المصفوفة الخطية Linear Array وهي أبسط أشكال المصفوفات تتكون من بُعد واحد وهو النوع الذي نشرحه في هذا المقال .
- المصفوفة غير خطية Non Linear Array وهي المصفوفة متعددة الأبعاد.
- الـ ArrayList تطبيق للخصائص القوائم List بواسطة مصفوفة خطية.
تُستخدم المصفوفات Arrays بشكل واسع في البرمجة لتنظيم البيانات والعمليات عليها. توفر لغة سي شارب العديد من الدوال والخصائص المفيدة للتعامل مع المصفوفات بطرق مختلفة.و يجدر بالذكر أنه يمكن استخدام مكتبات لغة سي شارب لتوفير دوال وأدوات إضافية للتعامل مع المصفوفات بشكل أكثر تعقيدًا وتخصيصًا.
المصفوفة الخطية Linear Array في C#
المصفوفة الخطية Linear Array في سي شارب هي مصفوفة يتم ترتيب البيانات فيها ببعد واحد، أيضاً المصفوفة الخطية Linear Array محدودة العناصر أي أن المصفوفة لها طول ثابت فهي توجد في Block واحد من الذاكرة يُحجزعند الإعلان عنها. ويتم الوصول إلى هذه العناصر بواسطة عنوان الفهرسة Indexing. كما يتم تحديد نوع العناصر للـ Array عند الإعلان عنها فالصيغة العامة للإعلان عن Array تكون كالتالي:
ArrayType[] ArrayName = new ArrayType[ Number of array's elements(array Length)];
من الصيغة العامة يتضح لنا أن بيان الإعلان عن المصفوفة Array في لغة سي شارب يبدأ بتحديد نوع البيانات للمصفوفة ثم الاقواس المربعة [ ] ثم اسم المصفوفة ثم معامل التعيين (=) وبما ان المصفوفة Object نستخدم كلمة new لنحدد بعدها نوع العناصر وعددها للمصفوفة حيث أن عدد العناصر هو طول المصفوفة Array Length مثلاً عندما نريد اعلان عن مصفوفة أرقام صحيحة Integer باسم A وعدد عناصر 5 ستكون طريقة تعريف المصفوفة Array في لغة سي شارب كالتالي :
int [ ] A = new [5];
عند الإعلان عن المصفوفة Array بهذه الطريقة سيتم اسناد قيم افتراضية للعناصر المصفوفة حسب نوع البيانات للمصفوفة فتكون القيم الافتراضية للعناصر الرقيمة 0 والمنطقية False و Null لغيرها يمكن كذلك إسناد القيم مباشرة للعناصر المصفوفة عند الإعلان يكون بيان الإعلان عن المصفوفة كالتالي:
int [ ] A = {7, 3, 0, -2, 1};
ويوضح الشكل التالي تمثيل لمصفوفة Array خطية من الأرقام الصحيحة وطريقة الفهرسة لعناصر المصفوفة:
من الشكل يتضح لنا أن طريقة الفهرسة Indexing للوصول إلى عناصر المصفوفة Array-Access يكون بكتابة اسم المصفوفة ومن ثم الأقواس المربعة Square Brackets [ ] . والقيم بين الأقواس تمثل ترتيب العنصر في المصفوفة حيث يبدأ ترتيب العناصر في المصفوفة من الصفر 0 ويمكن حساب طول المصفوفة يمكن من خلال خاصية طول المصفوفة Property Length.
لنأخذ مثال على طريقة تعريف المصفوفة Array ونرى كيف يتم تعيين القيم الإفتراضية للعناصر المصفوفة:
...........
int [] array ; //declaring an array named array.
//create the space for array and initialize to default zeros
array = new int[5]; // 5 int elements
Console.WriteLine("{0} {1,8}","index","value");
//output each array element's value
for(int i = 0; i < array.Length; i++)
Console.WriteLine("{0,5} {1,8}", i ,array[i]);
...........
الـ Output للمثال:
index value 0 0 1 0 2 0 3 0 4 0
في المثال رأينا طريقة المرور على عناصر المصفوفة وطباعتها من خلال حلقة التكرار for loop (المزيد في مقال عن حلقات التكرار loop في سي شارب) .كما استخدمت الخاصية length لتمثيل طول المصفوفة في الـ loop. نلاحظ أيضاً ترتيب العناصر يبدأ مع القيمة 0 ، والقيمة الافتراضية للعناصر الرقمية هي 0.
تعليمة foreach و المصفوفات Arrays في C#
مع المصفوفات Arrays في لغة سي شارب تستخدم حلقات التكرار Loop للوصول الى عناصر المصفوفة كلها للتعديل أو لطباعتها . وهنالك ايضاً تعليمة التكرار foreach التي يمكن أن تستخدم للوصول الى عناصر المصفوفة Array دون التعديل عليها فأي محاولة لتعديل قيمة معينة من قيم عناصر المصفوفة بواسطة foreach تعد خطأ برمجي، أي لا يمكن استخدام تعليمة foreach بدلاً من تعليمة for لإجراء عمليات على عناصر المصفوفة Array .
و يوضح المثال التالي طريقة استخدام foreach مع المصفوفة Array في سي شارب :
...........
int [] array = {1, 2 , 3};
//using foreach to print array's elements
foreach(int number in array)
Console.WriteLine(number);
...........
من المثال يتضح لنا بناء جملة foreach في لغة سي شارب يكون كتالي :
foreach( Type Identifier in ArrayName )
- Type Identifier النوع والمعرف هما نوع واسم لمتغير التكرار.
- الكلمة المحجوزة (in ) تنعي اختبر قيمة متغير التكرار إذا كانت موجودة في المصفوفة Array.
- ArrayName هو اسم المصفوفة Array التي يتم التكرار من خلالها.
في foreach يجب أن يتطابق نوع متغير التكرار مع نوع العناصر في المصفوفة. ويمثل متغير التكرار القيم المتتالية في المصفوفة عبر دورات التكرار المتتالية لعبارة foreach. و تدعم كثير من لغات البرمجة جملة foreach للعمل مع المصفوفات Arrays.
المصفوفة Array و الدوال Methods
في سي شارب يمكن تمرير المصفوفات Arrays كا Arguments لمعالجتها بواسطة دالة، وقد ناقشنا في مقال عن التعامل مع الدوال Methods في سي شارب طُرق تمرير المتغيرات عبر الدوال (Pass by Value and Pass by Reference) و أوضحنا تأثير طريقة التمرير الـ Arguments على القيم مع المتغيرات. فيما يلي سنناقش تأثير طريقة تمرير المصفوفة Array عبر دالة في C# على المصفوفة وعناصرها سواء كان التمرير بالقيمة Pass by value أو بالمرجع Pass by reference.
قبل البدء بمناقشة تمرير المصفوفات Array لابد أن نشرح الفرق في حالة تمرير قيمة لعنصر من عناصر المصفوفة أو تمرير المصفوفة كاملة. لابد أن نعرف أن أي تغيير على عنصر من عناصر المصفوفة من خلال دالة أو تعليمة سيؤثر على قيمة العنصر فالتعامل مع قيم عناصر المصفوفة يختلف عن التعامل مع المصفوفة كـ Object.
ففي حال تم تمرير قيمة عنصر معين من عناصر المصفوفة الى دالة وتمت معالجة قيمة هذا العنصر أو تمرير تمرير مصفوفة كا Argument وتمت معالجة كل العناصر عبر المرور على العناصر عنصر عنصر في المصفوفة هنا سيؤثر التغيير على قيم عناصر المصفوفة في خارج الدالة هذا لأننا نتعامل مع Object فنحن هنا نغير في بيانات هذا الـ Object لاحظ /ي نتائج المثال التالي لتتضح الفكرة:
class PassArray
{
public static void Main(string[] args)
{
int [] array = {1, 2, 3, 4, 5};
Console.WriteLine("Effects of passing reference to entier array:\n"+
"The values of the original array are:" );
//output original array elements
foreach (int value in array)
Console.Write(" {0}", value);
ModifyArray(array); //pass array reference
Console.WriteLine("\n\nThe values of the modified array are:" );
//output modified array elements
foreach (int value in array)
Console.Write(" {0}", value);
Console.WriteLine("\n\nEffects of passing array element Value:\n"+
"array[3] before ModifyElement: {0}", array[3] );
ModifyElement(array[3]); // attempt to modify array[3]
Console.WriteLine("array[3] after ModifyElement: {0}", array[3] );
}
public static void ModifyArray( int[] array2)
{
for (int counter = 0; counter < array2.Length; counter++)
array2[counter] *= 2;
}
public static void ModifyElement( int element)
{
element *= 2;
Console.WriteLine( "Value of element in ModifyElement: {0}", element);
}
}
لتكـن النتيـجـة
The values of the original array are: 1 2 3 4 5 The values of the modified array are: 2 4 6 8 10 Effects of passing array element Value: array[3] before ModifyElement: 8 Value of element in ModifyElement: 16 array[3] after ModifyElement: 8
في المثال السابق رأينا طريقة تمرير المصفوفة الى دالة وتمثل الطريقة المستخدمة أسلوب التمرير بالقيمة Pass by value ففي حال تمرير المصفوفة Array الى دالة Method ايضاً يكون التمرير على نوعين:
تمرير المصفوفة Array بالقيمة Pass by value وهنا ستأخذ الدالة نسختها من المصفوفة كـ Object وفي حال تعديل الدالة على قيم العناصر سيظهر التعديل على عناصر المصفوفة عنصر عنصر سيظهر التغيير على المصفوفة خارج الدالة . هذا لأن المصفوفة Object فالتغير في قيم العناصر عنصر عنصر يعتبر تغيير في بيانات الـ Object.
أما في حال التعديل على كامل المصفوفة والتعامل مع المصفوفة كا متغير هنا سيظهر التأثير على المصفوفة داخل الدالة فقط ولن يظهر على المصفوفة خارج الدالة. لاحظ /ي النتائج في المثال التالي :
class ArrayReferenceTest
{
public static void Main(string[] args)
{
//Careat and initialize arrayValue
int [] arrayValue = {1, 2, 3};
//copy the reference in variable arrayValue
int[] arrayValueCopy = arrayValue;
Console.WriteLine("Test passing arrayValue by value");
Console.Write("\ncontents of arrayValue before calling DoubleArray:\n\t");
//display content of arrayValue
foreach(int i in arrayValue)
Console.Write("{0} ", i);
//Pass variable arrayValue by value to DoubleArray
DoubleArray(arrayValue);
Console.Write("\ncontents of arrayValue after calling DoubleArray:\n\t");
//display content of arrayValue
foreach(int i in arrayValue)
Console.Write("{0} ", i);
//test whether reference was changed by DoubleArray
if ( arrayValue == arrayValueCopy)
Console.WriteLine("\n\nThe references refers to the same array ");
else
Console.WriteLine("\n\nThe references refers to the different arrays ");
}
public static void DoubleArray( int[] array)
{
//Double each element by value
for (int i = 0; i < array.Length; i++)
array[i] *= 2;
//create new object and assign its reference to array
array = new int[] {11 , 12, 13};
Console.Write("\n\nArray in the DoubleArray Method:\n\t");
foreach(int i in array)
Console.Write("{0} ", i);
}
}
لتكـن النتيـجـة
Test passing arrayValue by value contents of arrayValue before calling FirstDouble: 1 2 3 Array in the DoubleArray Method: 11 12 13 contents of arrayValue after calling DoubleArray: 2 4 6 The references refers to the same array
أيضاً يمكن تمرير المصفوفة Array بطريقة Pass by reference . وفي هذه الحالة سيتم استقبال المصفوفة Array مع الإشارة إلى مرجع ( Reference ) بمعنى الوصول الى موقع المصفوفة الأصلية في الذاكرة واستخدامه داخل الدالة لاحظ /ي النتائج في المثال التالي ليتضح الأمر:
class ArrayReferenceTest
{
public static void Main(string[] args)
{
//Careat and initialize ArrayRef
int [] ArrayRef = {1, 2, 3};
//copy the reference in variable ArrayRef
int[] ArrayRefyCopy = ArrayRef;
Console.WriteLine("\nTest passing ArrayRef reference by reference ");
Console.Write("\ncontents of ArrayRef before calling DoubleArray:\n\t");
//display content of ArrayRef
foreach(int i in ArrayRef)
Console.Write("{0} ", i);
//Pass variable ArrayRef by reference to DoubleArray
DoubleArray( ref ArrayRef);
Console.Write("\ncontents of ArrayRef after calling DoubleArray:\n\t");
//display content of ArrayRef after method call
foreach(int i in ArrayRef)
Console.Write("{0} ", i);
//test whether reference was changed by DoubleArray
if ( ArrayRef == ArrayRefyCopy)
Console.WriteLine("\n\nThe references refers to the same array ");
else
Console.WriteLine("\n\nThe references refers to the different arrays ");
}
public static void DoubleArray( ref int[] array)
{
//Double each element by value
for (int i = 0; i < array.Length; i++)
array[i] *= 2;
Console.Write("\n\nArray in the DoubleArray Method:\n\t");
foreach(int i in array)
Console.Write("{0} ", i);
//create new object and assign its reference to array
array = new int[] {11 , 12, 13};
}
}
لتكـن النتيـجـة
Test passing ArrayRef reference by reference contents of ArrayRef before calling DoubleArray: 1 2 3 Array in the DoubleArray Method: 2 4 6 contents of ArrayRef after calling DoubleArray: 11 12 13 The references refers to the different arrays
ملاحظة :
يعد تمرير المصفوفات Arrays والكائنات Objects حسب المرجع أمرًا منطقيًا لأسباب تتعلق بالأداء. إذا تم تمرير المصفوفات بالقيمة، فسيتم تمرير نسخة من كل عنصر. بالنسبة إلى المصفوفات الأكبر حجمًا والتي يتم تمريرها بشكل متكرر ، قد يؤدي ذلك إلى إضاعة الوقت يستهلك مساحة تخزين كبيرة لنسخ المصفوفات - تؤدي كلتا المشكلتين إلى ضعف الأداء .
تتوفر أمثلة هذا المقال هنا.
إلى هنا ينتهي هذا المقال الذي تعرفنا فيه على مفهوم المصفوفات Array في C# وطريقة تعريف مصفوفة Array في C# كما شرحنا جملة foreach وطريقة استخدامها للوصول إلى عناصر المصفوفة Array كما شرح المقال الفرق بين طُرق تمرير المصفوفة Array عبر الدوال سواء بالقيمة أو بالمرجع …تعتبر المصفوفات Arrays من هياكل بيانات القوية في لغة سي شارب حيث تسمح للمطورين بتخزين وتنظيم المجموعات من البيانات بشكل فعال. ويعد إتقان استخدام المصفوفات Arrays في لغة سي شارب مهمًا للمبرمجين لتطوير تطبيقات قوية وفعالة.