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

المصفوفات في C#: التصريح وLength والفرز والمصفوفات ثنائية الأبعاد والمسنّنة

المصفوفة في C# كتلة ثابتة الحجم من عناصر من نوع واحد. تعلّم كيف تصرّح بالمصفوفات وتهيّئها، وتقرأ Length، وتفرز وتبحث بالصنف Array، وتنسخها بأمان، وتعمل مع المصفوفات ثنائية الأبعاد والمسنّنة.

تحتوي هذه الصفحة على محررات قابلة للتشغيل - حرّر، شغّل، وشاهد النتيجة فوراً.

تحمل المصفوفة عددًا ثابتًا من العناصر من نوع واحد، مخزّنة متجاورة في الذاكرة. تختار الطول حين تنشئها، وتقرأ العناصر وتكتبها بفهرس يبدأ من الصفر، ولا يتغيّر الطول بعد ذلك أبدًا.

التصريح بمصفوفة وتهيئتها

نوع المصفوفة هو نوع العنصر متبوعًا بـ []. هناك عدة طرق لإنشاء واحدة:

المخرجات:

90, 0, 0, 72
Ben
2 prices, 3 days

تملأ new int[4] كل عنصر بالقيمة الافتراضية للنوع: 0 للأرقام، وfalse لـ bool، وnull للنصوص والأنواع المرجعية الأخرى. الشكل المختصر { "Ana", "Ben" } لا يعمل إلا في التصريح؛ وعند الإسناد إلى متغيّر موجود تحتاج إلى names = new[] { "Dev", "Eli" };.

Length والفهرسة والعنصر الأخير

تمتد الفهارس من 0 إلى Length - 1. Length خاصية، فلا أقواس لها (بخلاف الدالة Count() في LINQ).

المخرجات:

Count: 5
First: 18
Last: 16
Caught IndexOutOfRangeException

القراءة أو الكتابة خارج الحدود ترمي IndexOutOfRangeException وقت التشغيل؛ ولا يلتقطها المترجم. السبب المعتاد شرط حلقة مكتوب i <= arr.Length بدل i < arr.Length.

تضيف C# 8 وما بعدها صياغة الفهرس من النهاية والنطاق، وهي أقصر للعنصر الأخير وللشرائح:

int last = temps[^1];        // 16
int[] middle = temps[1..4];  // { 21, 25, 19 }, a new array

المرور على مصفوفة

تمنحك حلقة for الفهرس؛ وتمنحك foreach كل عنصر وهي الخيار الأوضح حين تقرأ فقط.

المخرجات:

4.95 | 13.20 | 3.58
Total: 21.73

متغيّر foreach للقراءة فقط: p = 0; داخل الحلقة خطأ ترجمة. لتغيير العناصر مرّ بفهرس.

الفرز والعكس والبحث

يحمل الصنف الساكن Array الدوال المساعدة. تفرز Array.Sort في المكان ولا تعيد شيئًا، فيضيع الترتيب الأصلي.

المخرجات:

Ascending:  60, 72, 79, 88, 95
Descending: 95, 88, 79, 72, 60
Index of 60: 4
Index of 99: -1
Any above 90: True
First below 75: 72
Ana, ben, chloe
fig, kiwi, banana

تعيد Array.IndexOf القيمة -1 حين تكون القيمة غائبة. وتعيد Array.Find القيمة الافتراضية للنوع (0 هنا) حين لا يطابق شيء، وهذا ملتبس مع الأرقام؛ استخدم Array.FindIndex حين يهمّ ذلك. والفرز التنازلي في استدعاء واحد هو Array.Sort(scores, (a, b) => b.CompareTo(a)).

إن احتجت إلى النتيجة المفروزة دون المساس بالأصل، يعيد LINQ مصفوفة جديدة: var sorted = scores.OrderBy(s => s).ToArray();. راجع LINQ.

تغيير الحجم: المصفوفة لا تكبر

الطول ثابت. تنشئ Array.Resize مصفوفة جديدة بالحجم المطلوب، وتنسخ العناصر، وتحدّث المتغيّر الذي تمرّره بـ ref.

المخرجات:

4
2
True
False

كل تغيير حجم ينسخ كل العناصر. تكبير مصفوفة عنصرًا عنصرًا في حلقة بطيء، وهو بالضبط ما تفعله List<T> عنك بكفاءة أكبر، بمضاعفة مصفوفتها الداخلية.

المصفوفات أنواع مرجعية: النسخ

إسناد مصفوفة إلى متغيّر آخر ينسخ المرجع لا العناصر. فيشير الاسمان إلى المصفوفة نفسها.

المخرجات:

100
2
0, 100, 2, 3, 0

وينطبق الأمر نفسه حين تمرّر مصفوفة إلى دالة: تستطيع الدالة تغيير عناصر المستدعي. تصنع Clone وArray.Copy وCopyTo وToArray() في LINQ كلها نسخة سطحية. وفي مصفوفة الكائنات تحمل المصفوفة الجديدة مراجع إلى الكائنات نفسها، فتغيير copy[0].Name ما زال يغيّر ما تراه original[0].

مقارنة المصفوفات بـ == تقارن المراجع. لمقارنة المحتوى استخدم a.SequenceEqual(b) من System.Linq.

المصفوفات ثنائية الأبعاد (متعددة الأبعاد)

تُصرَّح الشبكة المستطيلة بفاصلة داخل القوسين. وتُفهرس بالشكل [row, col].

المخرجات:

Rows: 2
Cols: 3
Length: 6, Rank: 2
. X . 
. . X 

Length في المصفوفة ثنائية الأبعاد العدد الكلي للعناصر (6 لشبكة 2 في 3)، ولهذا تستخدم الحلقات المتداخلة GetLength(0) وGetLength(1). وRank عدد الأبعاد. وتعمل الأبعاد الثلاثة بالطريقة نفسها: new int[4, 4, 4] وcube[x, y, z]. وتزور foreach على مصفوفة ثنائية الأبعاد كل عنصر صفًا بعد صف.

المصفوفات المسنّنة (مصفوفات من المصفوفات)

المصفوفة المسنّنة (jagged) int[][] مصفوفة عناصرها مصفوفات، ويمكن أن يكون لكل مصفوفة داخلية طولها الخاص. تناسب بيانات مثل "الطلبات لكل عميل" حيث تختلف الصفوف في الحجم.

المخرجات:

Customer 0: 2 orders, 20, 35
Customer 1: 1 orders, 12
Customer 2: 4 orders, 8, 15, 40, 22
True

تنشئ new int[3][] المصفوفة الخارجية فقط؛ ويبدأ كل صف null، وorders[0][0] قبل إسناد صف ترمي NullReferenceException. الصياغة new int[3][4] غير مسموحة؛ تنشئ كل صف بنفسك.

استخدم [,] لشبكة حقيقية (لوحة، مصفوفة رياضية، بكسلات) و[][] حين تختلف أطوال الصفوف أو تريد تبديل صفوف كاملة.

المصفوفة مقابل List

المصفوفة T[]List<T>
الحجمثابت عند الإنشاءيكبر ويصغر
العددالخاصية Lengthالخاصية Count
الإضافة أو الحذفغير ممكن (فقط Array.Resize)Add وInsert وRemove
متعددة الأبعاد[,] و[][]قوائم من القوائم فقط
الاستخدام النموذجيحجم معروف، جداول بحث، مخازنمجموعات تتغيّر

التحويل استدعاء واحد في الاتجاهين: new List<int>(arr) أو arr.ToList()، وlist.ToArray(). List<T> هي النسخة القابلة للنمو.

أخطاء شائعة

  • i <= arr.Length في حلقة. آخر فهرس صالح هو Length - 1؛ وهذا يرمي IndexOutOfRangeException.
  • طباعة المصفوفة مباشرة. تطبع Console.WriteLine(arr) القيمة System.Int32[]؛ استخدم string.Join.
  • توقّع أن تعيد Array.Sort المصفوفة المفروزة. تعيد void وتفرز في المكان.
  • النسخ بـ =. هذا ينسخ المرجع؛ استخدم Clone() أو ToArray().
  • استخدام صفوف المصفوفة المسنّنة قبل إنشائها. كل صف في new T[n][] يكون null حتى يُسند إليه.
  • استخدام Length لصفوف مصفوفة ثنائية الأبعاد. تعدّ كل العناصر؛ استخدم GetLength(0).

الأسئلة الشائعة

كيف أحصل على طول مصفوفة في C#؟

استخدم الخاصية Length: scores.Length. هي خاصية لا دالة، فلا أقواس. في المصفوفة ثنائية الأبعاد تكون Length العدد الكلي للعناصر؛ استخدم GetLength(0) لعدد الصفوف وGetLength(1) لعدد الأعمدة.

كيف أفرز مصفوفة في C#؟

تفرز Array.Sort(arr) المصفوفة في مكانها تصاعديًا. للترتيب التنازلي استدعِ Array.Reverse(arr) بعد الفرز، أو مرّر مقارنة: Array.Sort(arr, (a, b) => b.CompareTo(a)). وللحصول على نسخة مفروزة مع إبقاء الأصل استخدم LINQ: arr.OrderBy(x => x).ToArray().

ما الفرق بين المصفوفة ثنائية الأبعاد والمصفوفة المسنّنة في C#؟

المصفوفة ثنائية الأبعاد int[,] كتلة مستطيلة واحدة: لكل صف العدد نفسه من الأعمدة، وتفهرسها بالشكل grid[row, col]. أما المصفوفة المسنّنة int[][] فمصفوفة من المصفوفات: كل صف مصفوفة منفصلة يمكن أن يكون لها طولها الخاص، وتفهرسها بالشكل rows[i][j]. يجب إنشاء كل صف في المصفوفة المسنّنة قبل الاستخدام، وإلا يكون null.

هل يمكن تغيير حجم مصفوفة في C#؟

لا. يُحدَّد طول المصفوفة عند إنشائها. تبدو Array.Resize(ref arr, newSize) كأنها تغيّر الحجم، لكنها تحجز مصفوفة جديدة وتنسخ العناصر وتوجّه متغيّرك إلى الجديدة. إن كان الحجم يتغيّر كثيرًا فاستخدم List<T>.

لماذا تُظهر طباعة مصفوفة System.Int32[]؟

تستدعي Console.WriteLine(arr) الدالة arr.ToString()، والمصفوفات لا تتجاوزها، فتحصل على اسم النوع. اضمم العناصر في نص واحد بدلًا من ذلك: Console.WriteLine(string.Join(", ", arr)).

هل أستخدم مصفوفة أم List في C#؟

استخدم المصفوفة حين يكون عدد العناصر معروفًا وثابتًا، مثل الأشهر الاثني عشر أو لوحة لعبة. واستخدم List<T> حين تُضاف العناصر أو تُحذف مع الوقت. كلتاهما تفهرس في زمن ثابت، وList<T> تخزّن عناصرها في مصفوفة داخليًا.

Coddy programming languages illustration

تعلّم البرمجة مع Coddy

ابدأ الآن