struct — نوع قيمي مخصّص
struct يشبه class في الصياغة لكنه نوع قيمي: يُنسخ عند التمرير أو الإسناد بدل مشاركة نفس المرجع.
struct Point
{
public int X;
public int Y;
public Point(int x, int y) { X = x; Y = y; }
}
Point p1 = new Point(1, 2);
Point p2 = p1; // نسخة كاملة، ليست نفس البيانات
p2.X = 99;
Console.WriteLine(p1.X); // 1 — لم يتأثّر
Console.WriteLine(p2.X); // 99
متى تستخدم struct بدل class؟
| struct | class | |
|---|---|---|
| النوع | قيمي (نسخ) | مرجعي (مشاركة) |
| الحجم المناسب | صغير (بضع خانات) | متوسط إلى كبير |
| الوراثة | لا تدعمها | تدعمها |
| مثال جاهز | int, double, DateTime, Point | معظم أصنافك الخاصة |
💡 استخدم
structلبيانات صغيرة غير قابلة للتغيير غالبًا (إحداثية، لون، مبلغ)، وclassلكل ما عداه.
لماذا "صغيرة"؟ لأن كل إسناد وكل تمرير لدالة ينسخ الـ struct كاملًا. نسخ إحداثية من رقمين أرخص من تتبّع مرجع في الذاكرة، أما struct بعشرات الحقول يُمرَّر في حلقة فيُنسخ آلاف المرات، وهنا يصبح تمرير مرجع class واحد أسرع.
new Point() بدون وسائط متاح لأي struct حتى لو لم تكتب مُنشئًا بلا وسائط، ويعطيك نسخة كل حقولها بقيمها الافتراضية (0، false، null).
enum — مجموعة قيم ثابتة
يمنع الأرقام السحرية ويجعل الكود مقروءًا:
enum Season
{
Spring, // 0
Summer, // 1
Autumn, // 2
Winter // 3
}
Season current = Season.Autumn;
النوع الأساسي الافتراضي int والقيم تبدأ من 0. يمكن تخصيصه وإعطاء قيم صريحة:
enum HttpStatus : ushort
{
OK = 200,
NotFound = 404,
ServerError = 500
}
enum مع switch
string Describe(Season s) => s switch
{
Season.Spring => "ربيع",
Season.Summer => "صيف",
Season.Autumn => "خريف",
Season.Winter => "شتاء",
_ => "غير معروف"
};
التحويل بين enum و int
int code = (int)HttpStatus.NotFound; // 404
HttpStatus s = (HttpStatus)200; // HttpStatus.OK
bool valid = Enum.IsDefined(typeof(HttpStatus), 999); // false
⚠️ التحويل
(HttpStatus)999لا يفشل: يعطيك قيمة enum غير معرَّفة بصمت، لأن الـ enum في النهاية رقم. لذلك تحقّق بـEnum.IsDefinedمن أي رقم قادم من مصدر خارجي (قاعدة بيانات، طلب API) قبل الاعتماد عليه.
ومن النص إلى enum، استخدم Enum.TryParse بدل Enum.Parse حين قد يكون النص غير صالح:
if (Enum.TryParse("NotFound", out HttpStatus parsed))
Console.WriteLine((int)parsed); // 404
bit flags — دمج عدّة قيم
عندما يمثّل التعداد تركيبة اختيارات لا اختيارًا واحدًا، استخدم قوى 2 مع [Flags]:
[Flags]
enum FilePermission
{
None = 0,
Read = 1,
Write = 2,
Execute = 4
}
var p = FilePermission.Read | FilePermission.Write;
Console.WriteLine(p); // Read, Write
Console.WriteLine(p.HasFlag(FilePermission.Write)); // True
🎯 التالي: المطابقة النمطية (Pattern Matching).