الصفائف في Visual Basic

الصفيف هو مجموعة من قيم مرتبطة منطقياً مع بعضها البعض، مثل عدد الطلاب في كل صف في مدرسة لقواعد اللغة.

الصفيف يسمح لك بالإشارة إلى هذه القيم المرتبطة بالاسم نفسه و استخدام رقم، يدعى فهرس أو منخفض ، لإعلامهم عن جزء. يطلق على القيم المفردة عناصر الصفيف. تكون متجاورة من فهرس 0 إلى أعلى قيمة للفهرس.

على عكس الصفيف، المتغير الذي يحتوي على قيمة مفردة يدعى متغير رقمي.

المثال

يقوم المثال التالي بتعريف متغير صفيف لتقييد عدد الطلاب في كل صف في مدرسة قواعد اللغة.

Dim students(6) As Integer

الصفيف students في المثال السابق يحتوي على 7 عناصر. فهارس العناصر تتراوح من 0 إلى 6. هذا الصفيف أسهل من تعريف 7 متغيرات مختلفة.

يبين الرسم التوضيحي التالي الصفيف students. لكل عنصر من الصفيف:

  • فهرس العنصر يمثل صف (فهرس 0 يمثل روضة الأطفال).

  • القيمة الموجودة في العنصر تمثل عدد الطلاب في ذلك الصف.

عناصر الصفيف "students".

صورة الصفيف التي تُظهر عدد الطلاب

يبين المثال التالي كيفية الإشارة إلى أول وثاني وأخر عنصر في الصفيف students.

Dim kindergarten As Integer = students(0)
Dim firstGrade As Integer = students(1)
Dim sixthGrade As Integer = students(6)
MsgBox("Students in kindergarten = " & CStr(kindergarten))
MsgBox("Students in first grade = " & CStr(firstGrade))
MsgBox("Students in sixth grade = " & CStr(sixthGrade))

يمكنك الإشارة إلى الصفيف ككل باستخدام اسم متغير الصفيف فقط بدون فهارس.

أبعاد الصفيف

الصفيف students في المثال السابق يستخدم فهرس واحد فهو بذلك أحادي الأبعاد. يسمى الصفيف الذي يستخدم أكثر من فهرس أو منخفض متعدد الأبعاد. لمزيد من المعلومات، راجع أبعاد الصفيف في Visual Basic.

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

تعريف الصفيف

تقوم بتعريف متغير صفيف بنفس الطريقة كأي متغير أخر باستخدام العبارة Dim . اتبع اسم المتغير بزوج واحد أو أكثر من الأقواس للإشارة إلى أنه للاحتفاظ بصفيف بدلاً من متغير رقمي (متغير يحتوي على قيمة واحدة).

لتعريف متغير صفيف أحادي الأبعاد ، أضف زوجاً واحداً من الأقواس بعد اسم المتغير.

Dim cargoWeights() As Double

لتعريف متغير صفيف متعددة الأبعاد، أضف زوجاً واحداً من الأقواس بعد اسم المتغير و ضع فواصل داخل الأقواس لفصل الأبعاد.

Dim atmospherePressures(,,,) As Short

لتعريف متغير صفيف مزدحم، أضف عدد من أزواج الأقواس بعد اسم المتغير يساوي عدد مستويات الصفائف المتداخلة.

Dim inquiriesByYearMonthDay()()() As Byte

تعرّف الأمثلة السابقة متغيرات صفيف لكن لا تعيّن صفائف لهم. لا يزال يتوجب عليك إنشاء صفيف ، تهيئته، وتعيينه للمتغير.

الصفائف الفارغة

يسمى أيضا الصفيف بلا عناصر صفيف فارغ. المتغير الذي يحتوي على صفيف فارغ لا يملك القيمة Nothing. لإنشاء صفيف لا يحتوي على عناصر، قم بتعريف أحد أبعاد الصفيف ليكون -1، كما هو موضح في المثال التالي.

Dim twoDimensionalStrings(-1, 3) As String

قد تحتاج إلى إنشاء صفيف فارغ في ظل الظروف التالية:

  • تحتاج التعليمات البرمجية الخاصة بك للوصول إلى أعضاء الفئة Array ، مثل Length أو Rank، أو استدعاء دالة Visual Basic مثل UBound، دون مخاطرة استثناء NullReferenceException .

  • تريد أن تجعل التعليمات البرمجية المستهلِكة أبسط بعدم الحاجة إلى التحقق من Nothing كحالة خاصة.

  • التعليمات البرمجية الخاصة بك تتفاعل مع واجهة برمجة التطبيق (API) التي تتطلب منك تمرير صفيف فارغ إلى إجراء أو أكثر، أو التي تُرجّع صفيف فارغ من أجراء أو أكثر.

إنشاء الصفيف

يمكن إنشاء صفيف بطريقتين. يمكنك توفير حجم الصفيف عند تعريفة، أو، لأن الصفيف عبارة عن كائن فإنه يمكن إنشائه مع بند عامل تشغيل Visual Basic) New) وتعيينه إلى متغير الصفيف. يمكنك إجراء ذلك كجزء من تعريف الصفيف، أو في عبارة تعيين لاحقة كما هو موضح في المثال التالي.

cargoWeights = New Double() {}
atmospherePressures = New Short(,,,) {}
inquiriesByYearMonthDay = New Byte()()() {}

باتباع تنفيذ هذه العبارات، تصبح الصفائف فارغة.

ملاحظة

البند New يجب أن يحدد اسم النوع، متبوعاً بأقواس، متبوعاً بأقواس متعرجة ({}). لا تمثل الأقواس استدعاء للدالة الإنشائية للصفيف. بدلاً من ذلك، فإنها تشير إلى أن نوع الكائن هو نوع صفيف. يمكنك توفير قيم أولية داخل الأقواس. المحول البرمجي يتطلب الأقواس حتى إذا لم يتم توفير أي قيم. لذلك، البند New يجب أن يتضمن الأقواس و الأقواس المتعرجة، حتى و إن كانت هذه الأقواس فارغة. إذا قمت باستبعاد الأقواس المتعرجة يفترض المحول البرمجي أنك تقوم باستدعاء المُنشئ للنوع المحدد.

يمكنك تحديد حجم الصفيف بعدة طرق مختلفة. يمكنك توفير الحجم عند تعريف الصفيف كما هو موضح في المثال التالي.

Dim cargoWeights(10) As Double
Dim atmospherePressures(2, 2, 4, 10) As Short
Dim inquiriesByYearMonthDay(20)()() As Byte

يمكنك أيضاً توفير حجم الصفيف عند إنشائه بواسطة استخدام البند New ، كما هو موضح في المثال التالي.

cargoWeights = New Double(10) {}
atmospherePressures = New Short(2, 2, 4, 10) {}
inquiriesByYearMonthDay = New Byte(20)()() {}

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

' Assign a new array size and retain the current element values.
ReDim Preserve cargoWeights(20)
' Assign a new array size and retain only the first five element values.
ReDim Preserve cargoWeights(4)
' Assign a new array size and discard all current element values.
ReDim cargoWeights(15)

لمزيد من المعلومات، راجع كشف Vsual Basic) ReDim).

ملء صفيف بقيم أولية

يمكنك إنشاء صفيف يحتوي على مجموعة قيم أولية باستخدام قيمة حرفية للصفيف. تتكون القيمة الحرفية للصفيف من قائمة لقيم مفصولة بفاصلة، محاطة بأقواس متعرجة ({}).

عند إنشاء صفيف باستخدام القيمة الحرفية للصفيف، يمكنك إما توفير نوع الصفيف أو استخدام استنتاج النوع لتحديد نوع الصفيف. كلا الخيارين موضحين في التعليمات البرمجية التالية.

Dim numbers = New Integer() {1, 2, 4, 8}
Dim doubles = {1.5, 2, 9.9, 18}

عند استخدام استنتاج النوع يتم تحديد نوع الصفيف بواسطة النوع السائد في قائمة القيم التي تم توفيرها للقيمة الحرفية للصفيف . النوع السائد هو نوع فريد يمكن للأنواع الأخرى في القيمة الحرفية للصفيف أن تتوسّع له. إذا تعذر تحديد النوع الفريد هذا، فإن النوع السائد هو النوع الفريد الذي يمكن للأنواع الأخرى أن تضيق له. إذا تعذر تحديد هذين النوعين الفريدين، فإن النوع السائد هو Object. على سبيل المثال، إذا كانت قائمة القيم التي تم توفيرها للقيمة الحرفية للصفيف تحتوي على قيم من نوع Integer، Long، و Double، يكون صفيف الناتج من نوع Double. كلّا من Integer و Long يتوسعان لDouble و فقط Double. ولذلك، Double هو النوع السائد. لمزيد من المعلومات، راجع توسيع و تضييق التحويلات. تنطبق قاعدة الاستدلال هذه للأنواع المُشاره للصفائف التي تعتبر متغيرات محلية معرّفه في فئة عضو. على الرغم من أنه يمكنك استخدام قيم حرفية للصفيف عند إنشاء متغيرات مستوى الفئة، لا يمكن استخدام استنتاج النوع في مستوى الفئة. نتيجة لذلك، القيم الحرفية للصفيف المعينة في مستوى الفئة يشير إلى القيم التي تم توفيرها للقيمة الحرفية للصفيفه على أنها من نوع Object.

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

Dim values As Double() = {1, 2, 3, 4, 5, 6}

القيم الحرفية للصفائف المتداخلة

يمكنك إنشاء صفيف متعددة الأبعاد باستخدام القيم الحرفية للصفائف المتداخلة. القيم الحرفية للصفائف المتداخلة يجب أن يكون لها بعد و عدة أبعاد أو رتبة ، متناسقة مع الصفيف الناتج. ينشئ مثال التعليمات البرمجية التالي صفيف ثنائي الأبعاد من أعداد صحيحة باستخدام القيمة الحرفية للصفيف.

Dim grid = {{1, 2}, {3, 4}}

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

ملاحظة

يمكنك تجنب الخطأ عندما تقوم أنت بتوفير قيم حرفية للصفائف المتداخلة ذات الأبعاد المختلفة بواسطة إحاطة القيم الحرفية للصفيف الداخلي بأقواس. تجبر الأقواس تعبير القيمة الحرفية للصفيف ليتم تقييمها، و تستخدم القيمة الناتجة مع القيمة الحرفية للصفيف الخارجي . يظهر هذا في التعليمات البرمجية التالية.

Dim values = {({1, 2}), ({3, 4, 5})}

عند إنشاء صفيف متعددة الأبعاد باستخدام القيم الحرفية للصفائف المتداخلة، يمكنك استخدام استنتاج النوع. عند استخدام استنتاج النوع، النوع المشار إليه هو النوع السائد لكافة القيم في كافة القيم الحرفية للصفيف لمستوى التداخل. مثال التعليمات البرمجية التالي ينشئ صفيف ثنائي الأبعاد من نوع Double من قيم من نوع Integer و Double.

Dim a = {{1, 2.0}, {3, 4}, {5, 6}, {7, 8}}

لمزيد من الأمثلة، راجع كيفية القيام بما يلي: تـهيّئة متغيرات صفيف في Visual Basic.

تخزين قيم في صفيف

يمكنك الوصول إلى كل موقع في الصفيف باستخدام فهرس من نوع Integer. يمكن تخزين واسترداد قيم في صفيف بالإشارة إلى كل موقع في الصفيف باستخدام الفهرس الخاص به بين أقواس. فهارس الصفائف المتعددة الأبعاد مفصولة بفواصل (,). تحتاج فهرس واحد لكل بُعد في الصفيف. يوضح المثال التالي بعض العبارات لتخزين قيم في الصفيف.

Dim i = 4
Dim j = 2

Dim numbers(10) As Integer
Dim matrix(5, 5) As Double

numbers(i + 1) = 0
matrix(3, j * 2) = j

يوضح المثال التالي بعض العبارات للحصول على قيم من الصفيف.

Dim v = 2
Dim i = 1
Dim j = 1
Dim k = 1
Dim wTotal As Double = 0.0
Dim sortedValues(5), rawValues(5), estimates(2, 2, 2) As Double
Dim lowestValue = sortedValues(0)
wTotal += (rawValues(v) ^ 2)
Dim firstGuess = estimates(i, j, k)

لكل بُعد في الصفيف، يقوم الأسلوب GetUpperBound بإرجاع أعلى قيمة ممكنه للفهرس. أقل قيمة للفهرس هي 0 دائماً.

حجم الصفيف

حجم الصفيف هو حاصل ضرب كل أطوال الأبعاد. يمثل إجمالي عدد العناصر الموجودة حالياً في الصفيف.

يقوم المثال التالي بتعريف صفيف ثلاثي الأبعاد.

Dim prices(3, 4, 5) As Long

الحجم الإجمالي للصفيف في المتغير prices هو (3 + 1) x (4 + 1) x (5 + 1) = 120.

يمكن العثور على حجم الصفيف باستخدام خاصية Length . يمكن العثور على طول كل بعد في الصفيف المتعدد الأبعاد باستخدام الأسلوب GetLength .

يمكنك تغيير حجم متغير صفيف عن طريق تعيين كائن صفيف جديد له أو باستخدام العبارة ReDim .

هناك عدة أشياء تأخذ في الاعتبار عند التعامل مع حجم الصفيف.

طول البعد

الفهرس لكل بُعد يستند إلى 0 ، مما يعني أنه يتراوح من 0 إلى حده الأعلى. ولذلك، طول أي بعد معطى أكبر بمقدار 1 من الحد الأعلى المعرّف لذلك البعد.

حدود الطول

يتحدد طول كل بعد لصفيف إلى أقصى قيمة لنوع البيانات Integer ، وهو (2 ^ 31) - 1. ومع ذلك، الحجم الإجمالي لصفيف هو أيضاً محدد بالذاكرة المتوفر على النظام الخاص بك. عند محاولة تهيئة صفيف يتجاوز حجم الذاكرة RAM المتوفرة فإن وقت تشغيل اللغة العامة يطرح استثناء OutOfMemoryException .

الحجم وحجم العنصر

حجم الصفيف يكون مستقلاً عن نوع البيانات الخاص بعناصره. يمثل الحجم العدد الإجمالي للعناصر دائماً، ليس عدد البايت التي تستهلك في المخزن.

استهلاك الذاكرة

من غير الآمن طرح أية افتراضات حول كيفية تخزين الصفيف في الذاكرة. يختلف التخزين على الأنظمة الأساسية ذات قياسات عرض بيانات مختلفة ،بحيث يمكن لنفس الصفيف أن يستهلك ذاكرة على نظام 64-بت أكثر من استهلاكه للذاكرة على نظام 32-بت. ‏‫بناءً على تكوين النظام عند تهيئة الصفيف، يمكن لوقت تشغيل اللغة العامة (CLR) تعيين مخزن إما ليحزم العناصر لتكون اقرب إلى بعضها ما أمكن، أو ليبقيها كلها بمحاذاة حدود الأجهزة طبيعية. أيضاً، الصفيف يتطلب مقدار حمل للمخزن لمعلومات التحكم الخاصة به، ومقدار الحمل هذا يزيد بزيادة كل بعُد.

أنواع الصفيف وأنواع أخرى

أنواع البيانات

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

يرث كل صفيف من الفئة System.Array، و تستطيع تعريف متغير ليكون من نوع Array، ولكن لا يمكنك إنشاء صفيف من نوع Array. أيضاً،كشف Vsual Basic) ReDim) لا يمكنها العمل على متغير معرّف بالنوع Array. نظراً لهذه الأسباب، ومن أجل تأمين النوع، ينصح بتعريف كل صفيف كنوع محدد، مثل Integer في المثال السابق.

يمكنك معرفة نوع بيانات الصفيف أو عناصره بعدة طرق.

  • يمكنك استدعاء الأسلوب Object.GetType على المتغير لتستقبل كائن Type لنوع وقت تشغيل المتغير. الكائن Type يحتوي على معلومات شاملة في الخصائص والأساليب الخاصة به.

  • يمكنك تمرير المتغير إلى الدالة TypeName لتستقبل String يحتوي على اسم نوع وقت التشغيل.

  • يمكنك تمرير المتغير إلى الدالة VarType لتستقبل قيمة VariantType تمثل تصنيف نوع المتغير.

يستدعي المثال التالي الدالة TypeName لتحديد نوع الصفيف ونوع العناصر في الصفيف. نوع الصفيف Integer(,) والعناصر في الصفيف من نوع Integer.

Dim thisTwoDimArray(,) As Integer = New Integer(9, 9) {}
MsgBox("Type of thisTwoDimArray is " & TypeName(thisTwoDimArray))
MsgBox("Type of thisTwoDimArray(0, 0) is " & TypeName(thisTwoDimArray(0, 0)))

مجموعات كبديل للصفائف

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

إذا كنت بحاجة إلى تغيير حجم الصفيف يجب عليك استخدام كشف Vsual Basic) ReDim). عند القيام بذلك، Visual Basic تنشئ صفيف جديد و تحرر الصفيف السابق للتخلص منه. هذا يستغرق وقت لتنفيذه. لذلك، إذا كان عدد العناصر التي تعمل معها يتغير بشكل متكرر، أو لا يمكن التنبؤ بحد أقصى لعدد العناصر التي تحتاجها، قد تحصل على أداء أفضل باستخدام مجموعة.

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

مجموعات متخصصة

كما يوفر .NET Framework العديد من فئات و واجهات و بنيات لمجموعات عامة و خاصة. مساحات الأسماء System.Collections و System.Collections.Specialized تحتوي على ملفات تعريف و تطبيقات تتضمن قواميس و قوائم وقوائم الانتظار مكدسات. مساحة الاسم System.Collections.Generic توفر العديد من هذه في إصدارات عامة، تقبل وسيطة نوع واحدة أو اكثر.

إذا كانت المجموعة الخاصة بك تحتفظ بعناصر من نوع بيانات واحد فقط، المجموعة العامة تتميز بفرض تأمين النوع. لمزيد من المعلومات حول generics، راجع الـأنواع العامة في Visual Basic.

مجموعات متخصصة

كما يوفر .NET Framework العديد من فئات و واجهات و بنيات لمجموعات عامة و خاصة. مساحات الأسماء System.Collections و System.Collections.Specialized تحتوي على ملفات تعريف و تطبيقات تتضمن قواميس و قوائم وقوائم الانتظار مكدسات. مساحة الاسم System.Collections.Generic توفر العديد من هذه في إصدارات عامة، تقبل وسيطة نوع واحدة أو اكثر.

إذا كانت المجموعة الخاصة بك تحتفظ بعناصر من نوع بيانات واحد فقط، المجموعة العامة تتميز بفرض تأمين النوع. لمزيد من المعلومات حول generics، راجع الـأنواع العامة في Visual Basic.

المثال

يستخدم المثال التالي فئة .NET Framework العامة System.Collections.Generic.List<T> لإنشاء مجموعة من قائمة كائنات Customer .

' Define the class for a customer.
Public Class Customer
    Public Property Name As String
    ' Insert code for other members of customer structure.
End Class

' Create a module-level collection that can hold 200 elements.
Public CustomerList As New List(Of Customer)(200)

' Add a specified customer to the collection.
Private Sub AddNewCustomer(ByVal newCust As Customer)
    ' Insert code to perform validity check on newCust.
    CustomerList.Add(newCust)
End Sub

' Display the list of customers in the Debug window.
Private Sub PrintCustomers()
    For Each cust As Customer In CustomerList
        Debug.WriteLine(cust)
    Next cust
End Sub

تعريف مجموعة CustomerFile يحدد أنه يمكن أن تحتوي على عناصر من النوع Customer فقط. كما توفر سعة أولية لـ 200 عنصر . الإجراء AddNewCustomer يتحقق من صحة العنصر الجديد ومن ثم يضيفه إلى المجموعة. الإجراء PrintCustomers يستخدم التكرار الحلقي For Each لعبور المجموعة وعرض عناصرها.

مواضيع ذات صلة

راجع أيضًا:

المرجع

عبارة Vsual Basic) Dim)

كشف Vsual Basic) ReDim)

Array