آرایهها یکی از پایهایترین و در عین حال قدرتمندترین ساختارهای داده تو هر زبان برنامهنویسیه. درک عمیقشون برای نوشتن کدهای بهینه و کارآمد، حیاتیه. بیاید یه شیرجه عمیق بزنیم تو دنیای آرایهها در #C و تمام جزئیاتش رو یاد بگیریم.
1️⃣شالوده آرایه: تعریف، ساختار و دسترسی
آرایه، مجموعهای با تعداد ثابت از متغیرهاست که همگی از یک نوع مشخص هستن.
نکته کلیدی پرفورمنس:
عناصر یک آرایه، همیشه در یک بلوک حافظه پشت سر هم و یکپارچه (Contiguous) قرار میگیرن که باعث دسترسی فوقالعاده سریع به هر کدوم از عناصر میشه.
نحوه تعریف و دسترسی:
آرایه رو با [] بعد از نوع داده مشخص میکنیم. برای دسترسی به هر عنصر (element) هم از ایندکس اون استفاده میکنیم که از صفر شروع میشه.
// یک آرایه از نوع char با ظرفیت ۵ عنصر تعریف میکنیم
char[] vowels = new char[5];
// به هر عنصر با ایندکسش دسترسی پیدا میکنیم
vowels[0] = 'a';
vowels[1] = 'e';
vowels[2] = 'i';
vowels[3] = 'o';
vowels[4] = 'u';
Console.WriteLine(vowels[1]); // خروجی: e
2️⃣مقداردهی و پیمایش: از روش کلاسیک تا C# 12
برای کار با تمام عناصر یک آرایه، معمولاً از حلقهها استفاده میکنیم. پراپرتی .Length هم به ما تعداد کل عناصر آرایه رو میده.
for (int i = 0; i < vowels.Length; i++)
{
Console.Write(vowels[i]); // خروجی: aeiou
}
نکته:
بعد از ساختن یک آرایه، طول (ظرفیت) آن دیگر قابل تغییر نیست. برای ساختارهای داده با اندازه داینامیک، باید از کالکشنهای پیشرفتهتری که در System.Collection وجود داره استفاده کرد.
مقداردهی اولیه سریع:
میتونید موقع تعریف، مستقیماً آرایه رو مقداردهی کنید:
// روش قدیمیتر
char[] vowels = new char[] {'a','e','i','o','u'};
// روش سادهتر
char[] vowels = {'a','e','i','o','u'};
روش مدرن (از C# 12):
Collection Expressions
از C# 12 به بعد، میتونید از [] به جای {} برای مقداردهی اولیه استفاده کنید. مزیت بزرگش اینه که میتونید مستقیماً اون رو به متدها پاس بدید:
// تعریف آرایه با سینتکس جدید
char[] vowels = ['a','e','i','o','u'];
// پاس دادن مستقیم به یک متد
PrintLetters(['x', 'y', 'z']);
3️⃣راز مقداردهی پیشفرض (Default Initialization)
وقتی یک آرایه رو میسازید، عناصرش هیچوقت خالی نیستن! #C همیشه اونها رو با مقدار پیشفرضِ نوع دادهشون پر میکنه. این کار با صفر کردن بیتهای حافظه (bitwise zeroing) انجام میشه.
برای انواع عددی مثل int، مقدار پیشفرض 0 است.
برای bool، مقدار پیشفرض false است.
برای تمام Reference Typeها (مثل string یا کلاسها)، مقدار پیشفرض null است.
int[] numbers = new int[1000];
Console.WriteLine(numbers[123]); // خروجی: 0
4️⃣مهمترین بحث: آرایهی Value Type در برابر Reference Type
یادتونه در مورد تفاوت Value و Reference Type حرف زدیم؟ اینجا خودشو به بهترین شکل نشون میده!
آرایهای از Value Type (مثل struct):
وقتی آرایهای از structها میسازید، خودِ آبجکتها به صورت فیزیکی و پشت سر هم در اون بلوک حافظه قرار میگیرن.
public struct Point { public int X, Y; }
Point[] points = new Point[1000];
// اینجا ما ۱۰۰۰ آبجکت Point کامل در حافظه داریم
// و مقدار پیشفرض هر X و Y در آنها، صفر است
Console.WriteLine(points[500].X); // خروجی: 0 آرایهای از Reference Type (مثل class):
اما وقتی آرایهای از classها میسازید، اون بلوک حافظه فقط با ۱۰۰۰ تا رفرنس null پر میشه! هنوز هیچ آبجکتی ساخته نشده.
public class Point { public int X, Y; }
Point[] points = new Point[1000];
// اینجا ما فقط ۱۰۰۰ تا جای خالی (null) داریم
// این کد خطای NullReferenceException میده!
// چون points[500] نال است و X ندارد.
// int x = points[500].X; // ❌ BOOM!راه حل: باید بعد از ساختن آرایه، در یک حلقه، هر عنصر رو به صورت جداگانه با new بسازید:
for (int i = 0; i < points.Length; i++)
{
points[i] = new Point(); // ساختن هر آبجکت به صورت مجزا
}
5️⃣نکات تکمیلی و کلیدی
نکته 1: خودِ آرایه، همیشه یک Reference Type است، حتی اگه عناصر داخلش Value Type باشن. این یعنی میتونید یه رفرنس آرایه داشته باشید که null باشه:
int[] myArray = null;
نکته 2: تمام آرایهها در #C به صورت پنهان از کلاس System.Array ارثبری میکنند که یک سری متدهای عمومی و کاربردی رو در اختیارشون میذاره.