الـ ArrayList هو نوع بيانات مهم في C#، بيُعتبر واحد من الـ Non-Generic Collections وموجود في الـ namespace اللي اسمه System.Collections.
الـ ArrayList بيساعدك تتعامل مع مجموعة من العناصر بمرونة أكبر من الـ Array العادي، وبيحل كتير من المشاكل اللي كانت بتواجهنا معاه.
Key Differences: Array vs. ArrayList
قبل ما ندخل في تفاصيل الـ ArrayList، خلينا نقارنه بالـ Arrays in CSharp العادي عشان نفهم الفروقات الأساسية.
| Feature | Array | ArrayList |
|---|---|---|
| Size | حجم ثابت (Fixed Length). | حجم متغير (Variable Length)، بيزيد ويقل ديناميكيًا. |
| Type Safety | آمن من ناحية النوع (Strongly Typed)، بيخزن نوع واحد بس. | غير آمن (Not Type-Safe)، بيقدر يخزن أنواع مختلفة. |
| Performance | أداء أسرع لعدم وجود Boxing/Unboxing. | أداء أبطأ نسبيًا بسبب عمليات الـ Boxing/Unboxing. |
| Flexibility | صعب تضيف أو تحذف عناصر من النص. | سهل جدًا تضيف أو تحذف عناصر من أي مكان. |
How ArrayList Works: Cs Boxing and Unboxing
السبب الرئيسي إن ArrayList بيقدر يخزن أي نوع بيانات هو إنه بيحول أي عنصر بيتحط جواه لنوع object. العملية دي ليها تأثير مهم على الأداء.
Boxing
لما بنضيف أي value type (زي int, bool, double) جوه ArrayList، بيتم تحويله تلقائيًا لـ object. العملية دي اسمها Boxing.
int x = 5;
object obj = x; // This is BoxingUnboxing
لما بنسترجع قيمة من ArrayList، بنحتاج نعمل العملية العكسية عشان نرجعها لنوعها الأصلي. العملية دي اسمها Unboxing وبتتطلب Explicit Casting.
object obj = 5;
int x = (int)obj; // This is Unboxingعمليات الـ Boxing and Unboxing دي بتستهلك موارد إضافية من الذاكرة والـ processor، وده ممكن يأثر على أداء التطبيق، خصوصًا في العمليات الكبيرة والمتكررة.
Creating an ArrayList
فيه أكتر من طريقة عشان ننشئ ArrayList:
- الـ Empty ArrayList: بينشئ
ArrayListفاضي بالـcapacityالافتراضية.ArrayList arrayList = new ArrayList(); - الـ With Capacity: بينشئ
ArrayListفاضي لكن بيحدد الـcapacityالأولية بتاعته (عدد العناصر اللي يقدر يشيلها قبل ما يحتاج يزود حجمه).ArrayList arrayListWithCapacity = new ArrayList(10); - الـ From Another Collection: بينشئ
ArrayListجديد ويحط فيه عناصر منcollectionتانية موجودة.int[] myArr = { 10, 20, 30 }; ArrayList arrayListFromCollection = new ArrayList(myArr);
Adding Elements
Add() and AddRange()
- الـ
Add(): بتضيف عنصر واحد في آخر الـArrayList. - الـ
AddRange(): بتضيف مجموعة عناصر مرة واحدة منcollectionتانية. الـmethodدي بتاخد أيcollectionبتطبق الـinterfaceاللي اسمهICollection.
ArrayList list = new ArrayList();
// Add single elements of different types
list.Add(1);
list.Add("Test");
list.Add(true);
list.Add(4.5);
list.Add(null);
list.Add("Test"); // Duplicates are allowed
// Add a range of elements from an array
list.AddRange(new int[] { 10, 20, 30 });Accessing and Modifying Elements
بنقدر نوصل لأي عنصر عن طريق الـ index بتاعه، زي الـ Array بالظبط.
Console.WriteLine(list[0]); // Outputs: 1
Console.WriteLine(list[1]); // Outputs: "Test"
// When retrieving, you need to cast it back to its original type
int firstElement = (int)list[0];
string secondElement = (string)list[1];وبرضو نقدر نعدل قيمة أي عنصر بنفس الطريقة:
list[0] = 101; // Update the value at index 0Iterating Through an ArrayList
لإن الـ ArrayList بيعتبر Cs Enumerable، نقدر نلف على كل عناصره باستخدام for أو foreach loops.
// Using foreach (the variable must be var or object)
foreach (var item in list)
{
Console.WriteLine(item);
}
// Using for loop with the .Count property
for (int i = 0; i < list.Count; i++)
{
Console.WriteLine(list[i]);
}Inserting Elements
Add() vs. Insert()
- الـ
Add(): دايمًا بتضيف العنصر في الآخر. - الـ
Insert(): بتضيف العنصر في مكان (index) معين إنت بتحدده.
list.Insert(2, "New Value"); // Inserts "New Value" at index 2ممكن كمان تضيف مجموعة عناصر في مكان معين باستخدام
InsertRange(index, collection).
Removing Elements
عندنا أكتر من method لحذف العناصر:
- الـ
Remove(value): بتحذف أول ظهور للعنصر اللي قيمته مطابقة للقيمة اللي بتحددها. - الـ
RemoveAt(index): بتحذف العنصر اللي فيindexمعين. - الـ
RemoveRange(index, count): بتحذف عدد معين من العناصر (count) بداية منindexمعين. - الـ
Clear(): بتحذف كل العناصر من الـArrayList، لكن الـCapacityبتاعته بتفضل زي ما هي.
// Assuming list contains: { 1, "Test", true, "Test" }
list.Remove("Test"); // Removes the first "Test", list becomes { 1, true, "Test" }
list.RemoveAt(0); // Removes the element at index 0, list becomes { true, "Test" }
list.RemoveRange(0, 2); // Removes the first two elementsSearching and Checking
- الـ
Contains(value): بترجعtrueلو العنصر موجود، وfalseلو مش موجود. - الـ
IndexOf(value): بترجع الـindexبتاع أول ظهور للعنصر. لو مش موجود، بترجع-1. ممكن كمان تحددلهindexيبدأ يدور من عنده.
bool hasTest = list.Contains("Test"); // true
int index = list.IndexOf("Test"); // 1
// Start searching for "Test" from index 2
int nextIndex = list.IndexOf("Test", 2); Other Useful Methods
- الـ
Clone(): بتعملshallow copyمن الـArrayListوبترجعه كـobject، فلازم نعملهcast. - الـ
CopyTo(): بتنسخ عناصر الـArrayListلـarrayعادية. - الـ
Sort(): بترتب العناصر تصاعديًا باستخدامQuickSort algorithm.
ArrayList listToSort = new ArrayList() { "USA", "India", "UK" };
listToSort.Sort();
// listToSort now contains: { "India", "UK", "USA" }The Verdict: Why ArrayList is Not Recommended
بالرغم من مرونة الـ ArrayList، هي مبقتش الخيار المفضل في C# الحديثة، وده للأسباب دي:
- الأداء (Performance): عمليات الـ
BoxingوUnboxingالمستمرة بتأثر على الأداء بشكل ملحوظ في التطبيقات الكبيرة. - أمان النوع (Type Safety): لإنها بتقبل أي نوع، ممكن تحصل أخطاء
runtimeبسبب محاولةcastنوع غلط.
الحل الأفضل والأحدث هو استخدام الـ Generic List اللي هي List<T>.
الـ List<T> بتدينا نفس المرونة الديناميكية في الحجم، لكنها strongly typed، وده بيحل مشكلة الأداء ومشاكل الـ runtime errors المتعلقة بالأنواع.