الإصدار الأحدث · C# 13 · .NET 9 · 2026

تعلم
من الصفر للاحتراف

دليل شامل يغني عن الكورسات — من أول سطر كود حتى الاحتراف في OOP، بمشروع Console تطبيقي كامل يؤهّلك لدخول عالم Backend بثقة.

محدّث 30 مايو 2026
C# 13 / .NET 9
30 قسم + مشروع Console تطبيقي
بقلم Yahya.DEV
13
إصدار C# الحالي
30
قسم تعليمي كامل
75+
مثال كود حقيقي
1
مشروع Console مستقل

من أين تبدأ؟

الدورة مقسّمة إلى مستويات واضحة — اتبع الترتيب للحصول على أفضل نتيجة.

⚡ مبتدئ

الأساسيات

ابدأ هنا إذا كنت جديداً تماماً في البرمجة

  • ما هي C# وتاريخها
  • البيئة وأول برنامج
  • 🧠 العقلية الخلفية: CLR وStack/Heap
  • المتغيرات والأنواع
  • العمليات والتحكم
  • الحلقات والمصفوفات
  • 🎯 تطبيق: نظام تقييم طلاب
🔥 متوسط

البرمجة كائنية

الجوهر الحقيقي للغة — OOP كاملاً

  • الكلاسات والكائنات
  • الوراثة والتغليف
  • الواجهات والتجريد
  • 🪲 مطبات OOP الشائعة
  • الـ Generics
  • المجموعات Collections
  • 🎯 تطبيق: نظام مكتبة
💎 متقدم

الاحتراف

ما يُميّز المبرمج المحترف

  • LINQ بالكامل
  • Delegates & Events
  • Async / Await
  • معالجة الأخطاء
  • 🪲 مطبات Async والأخطاء
🚀 خبير

C# الحديثة

أحدث ميزات C# 13 و .NET 9

  • Pattern Matching
  • Records & Structs
  • Nullable Reference Types
  • Source Generators
  • Performance & Spans
🏗️ مشروع

مشروع التخرّج

طبّق كل ما تعلّمته في تطبيق Console حقيقي

  • Console App منظّم بـ OOP
  • Record & Enum Types
  • Repository Pattern
  • حفظ البيانات بـ JSON
  • 🏁 تحدي مستقل نهائي
⚡ مبتدئ
01

ما هي لغة C#؟

نظرة شاملة — التاريخ، الاستخدامات، لماذا C# في 2026؟

C# (سي شارب) هي لغة برمجة حديثة متعددة الأغراض، طوّرتها شركة Microsoft عام 2000 بقيادة المهندس Anders Hejlsberg (مؤلف Turbo Pascal وDelphi). تعمل على إطار .NET وتُعدّ اليوم من أقوى اللغات وأكثرها توظيفاً في العالم.

"C# تجمع قوة C++ مع بساطة Java مع مرونة Python — في لغة واحدة موثوقة ومُطوَّرة باستمرار."
أبرز استخدامات C# في 2026:
  • 🎮 تطوير الألعاب — Unity (المحرك الأشهر في العالم) يعتمد C# بالكامل
  • 🌐 تطوير الويب — ASP.NET Core لبناء APIs وتطبيقات ويب سريعة
  • 📱 تطبيقات الموبايل — .NET MAUI لـ iOS وAndroid
  • 🖥️ تطبيقات سطح المكتب — WPF وWinForms وMAUI
  • ☁️ الـ Cloud والـ Microservices — Azure-native
  • 🤖 الذكاء الاصطناعي والـ ML — ML.NET
C# 13 — أول برنامج
// أول برنامج C# — Hello World (أسلوب Top-Level في C# 9+)
Console.WriteLine("مرحباً بالعالم من Yahya.DEV! 🚀");
Console.WriteLine($"تاريخ اليوم: {DateTime.Now:dd/MM/yyyy}");

// أو بالأسلوب الكلاسيكي:
namespace MyFirstApp;

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("مرحباً بالعالم!");
    }
}
// OUTPUT
مرحباً بالعالم من Yahya.DEV! 🚀
تاريخ اليوم: 30/05/2026
إصدارسنة الإصدارأبرز الميزات
C# 1.02002البداية مع .NET Framework
C# 3.02007LINQ, Lambda, var
C# 5.02012async / await
C# 8.02019Nullable, Switch Expressions
C# 10.02021Global using, File-scoped namespace
C# 12.02023Primary Constructors, Collection Expressions
C# 13.02024/2025params collections, Lock type, escape sequences
⚡ مبتدئ
02

بيئة العمل وأول برنامج

Visual Studio, VS Code, .NET CLI — كيف تبدأ فوراً

ثلاث طرق لبدء كتابة C#:
  • 🔵 Visual Studio 2022 — البيئة الأقوى (Windows / Mac) — مجاني للأفراد
  • VS Code + C# Extension — خفيف وسريع — يعمل على كل الأنظمة
  • 🌐 dotnet.microsoft.com/fiddle — مباشرة في المتصفح بدون تثبيت
Terminal — إنشاء مشروع جديد
# تثبيت .NET 9 SDK أولاً من: https://dotnet.microsoft.com/download

# إنشاء مشروع Console
dotnet new console -n MyProject

# الدخول للمجلد
cd MyProject

# تشغيل البرنامج
dotnet run
💡
نصيحة: ابدأ بـ VS Code مع إضافة "C# Dev Kit" — أسرع للتعلم ويعمل على Windows وMac وLinux بدون مشاكل.
🧠 عقلية المبرمج
🧠

العقلية الخلفية: كيف تُنفَّذ أكوادك فعلياً؟

Compilation → IL → CLR → JIT، وStack vs Heap

قبل أن تكتب سطراً واحداً آخر، يجب أن تفهم سؤالاً جوهرياً: عندما تضغط Run، ماذا يحدث بالضبط بين كتابتك للكود وظهور النتيجة على الشاشة؟ هذا الفهم هو ما يفرّق بين من "يحفظ الصيغ" ومن يفهم اللغة فعلياً.

C# ليست لغة تُترجَم مباشرة لتعليمات المعالج كما في C/C++ — بل تمر بخطوة وسيطة ذكية تجعلها تعمل على Windows وLinux وmacOS بنفس الكود تماماً.
📝
1. كودك C#

ملفات .cs التي تكتبها بنفسك

⚙️
2. مترجم Roslyn

يحوّل الكود إلى IL (لغة وسيطة، ليست لغة المعالج)

📦
3. Assembly (.dll)

ملف يحتوي IL + بيانات وصفية (Metadata)

🚀
4. CLR + JIT

عند التشغيل، JIT يحوّل IL لتعليمات معالج حقيقية

📌
لماذا هذا مهم؟ هذا بالضبط سبب عمل C# على أي نظام تشغيل لديه CLR مناسب (.NET Runtime) — كودك المُترجَم (IL) واحد، والـ JIT الخاص بكل نظام هو من "يُترجمه" أخيراً لتعليمات تلك المعالج. هذا أيضاً ما يسمح لـ Garbage Collector بإدارة الذاكرة تلقائياً — جزء من بيئة CLR نفسها.
الذاكرة: Stack مقابل Heap — أهم تفصيل ستحتاجه لفهم باقي الكورس

كل متغير في برنامجك يعيش في مكان واحد من اثنين، وهذا يحدّد سلوكه بالكامل:

الخاصيةStack (المكدّس)Heap (الكومة)
من يعيش هنا؟Value Types: int, double, bool, structReference Types: class, string, array, object
السرعةسريع جداً — تنظيم تلقائي صارمأبطأ نسبياً — يحتاج تتبّعاً
التنظيفيُحذف فوراً عند خروج الدالةيُنظَّفه Garbage Collector لاحقاً
ما يحمله المتغيرالقيمة الفعلية مباشرةمرجع (Reference) يشير لموقع البيانات في Heap
C# — أثر عملي لـ Value vs Reference
// Value Type — كل متغير له نسخته الخاصة على Stack
int a = 10;
int b = a;     // نسخة جديدة كاملة
b = 99;
Console.WriteLine(a); // 10 — لم يتأثر a أبداً

// Reference Type — المتغيران يشيران لنفس الكائن في Heap
var arr1 = new int[] { 1, 2, 3 };
var arr2 = arr1;   // arr2 يشير لنفس المصفوفة، لا نسخة جديدة
arr2[0] = 99;
Console.WriteLine(arr1[0]); // 99 — تأثّر arr1 أيضاً!
// OUTPUT
10
99
⚠️
هذا الفرق سيفسّر لك لاحقاً ظواهر "غريبة" كثيرة — مثل تعديل خاصية كلاس داخل دالة فيؤثر على الأصل (لأنه مرجع)، بعكس تعديل قيمة int في دالة فلا يتغيّر شيء بالخارج. احتفظ بهذا الجدول في ذهنك طوال الكورس.
⚡ مبتدئ
03

المتغيرات والأنواع

كل أنواع البيانات في C# — Value Types vs Reference Types

في C# كل متغير له نوع محدد. اللغة strongly-typed — أي المُترجم يتحقق من الأنواع قبل التشغيل.

C# — المتغيرات والأنواع الأساسية
// ==============================
// 1. أنواع الأعداد الصحيحة
// ==============================
int     age    = 25;          // -2.1B إلى 2.1B   (32-bit)
long    pop    = 8_000_000_000L; // أعداد كبيرة جداً  (64-bit)
short   x      = 1000;        // -32K إلى 32K      (16-bit)
byte    b      = 255;         // 0 إلى 255          (8-bit)

// ==============================
// 2. أنواع الأعداد العشرية
// ==============================
double  pi     = 3.14159265; // دقة عالية          (64-bit)
float   temp   = 36.6f;      // دقة متوسطة         (32-bit)
decimal price  = 99.99m;     // للمال والدقة القصوى (128-bit)

// ==============================
// 3. النصوص والحروف
// ==============================
string  name   = "Yahya";
char    grade  = 'A';        // حرف واحد فقط — single quotes

// ==============================
// 4. المنطق Boolean
// ==============================
bool    isActive = true;
bool    isEmpty  = false;

// ==============================
// 5. var — استنتاج النوع تلقائياً
// ==============================
var city    = "Riyadh";   // string  (يحدده المترجم)
var count   = 42;         // int
var ratio   = 3.14;       // double

// ==============================
// 6. الثوابت const
// ==============================
const double PI = 3.14159265358979;
const string APP_NAME = "Yahya.DEV";

// ==============================
// 7. String Interpolation (C# 6+)
// ==============================
string msg = $"مرحباً {name}، عمرك {age} سنة";
Console.WriteLine(msg);
// OUTPUT
مرحباً Yahya، عمرك 25 سنة
النوعالحجمالمدىمثال
int4 bytes±2.1 مليارint x = 42;
long8 bytes±9.2 كوينتيليونlong y = 9L;
double8 bytes±1.8×10³⁰⁸double d = 3.14;
decimal16 bytes±7.9×10²⁸decimal m = 9.99m;
bool1 bytetrue / falsebool b = true;
char2 bytesUnicodechar c = 'A';
stringمتغيرنص غير محدودstring s = "hi";
⚡ مبتدئ
04

العمليات والتحكم في التدفق

if, else, switch, Ternary operator

C# — التحكم في التدفق
int score = 85;

// ==============================
// if / else if / else
// ==============================
if (score >= 90)
    Console.WriteLine("ممتاز 🌟");
else if (score >= 75)
    Console.WriteLine("جيد جداً 👍");
else if (score >= 60)
    Console.WriteLine("جيد");
else
    Console.WriteLine("راجع المادة");

// ==============================
// Ternary Operator ?: (مختصر)
// ==============================
string result = score >= 60 ? "ناجح ✅" : "راسب ❌";
Console.WriteLine(result);

// ==============================
// Switch Expression (C# 8+ الحديث)
// ==============================
string grade = score switch
{
    >= 90 => "A",
    >= 80 => "B",
    >= 70 => "C",
    >= 60 => "D",
    _      => "F"   // _ = default
};
Console.WriteLine($"التقدير: {grade}");

// ==============================
// Null Coalescing ?? و ?.
// ==============================
string? userName = null;
string  display  = userName ?? "زائر";       // إذا null → "زائر"
int?    len      = userName?.Length;         // إذا null → null (لا crash)
// OUTPUT
جيد جداً 👍
ناجح ✅
التقدير: B
⚡ مبتدئ
05

الحلقات (Loops)

for, while, do-while, foreach

C# — الحلقات الأربعة
// ==============================
// 1. for — عدد معروف مسبقاً
// ==============================
for (int i = 1; i <= 5; i++)
    Console.WriteLine($"رقم {i}");

// ==============================
// 2. while — شرط غير معروف
// ==============================
int count = 0;
while (count < 3)
{
    Console.WriteLine($"count = {count}");
    count++;
}

// ==============================
// 3. do-while — ينفّذ مرة على الأقل
// ==============================
int x = 10;
do
{
    Console.WriteLine($"x = {x}");
    x--;
} while (x > 8);

// ==============================
// 4. foreach — للمجموعات
// ==============================
string[] langs = { "C#", "Python", "JavaScript" };
foreach (string lang in langs)
    Console.WriteLine($"لغة: {lang}");

// break و continue
for (int i = 0; i < 10; i++)
{
    if (i == 3) continue;  // تخطّ 3
    if (i == 6) break;     // أوقف عند 6
    Console.Write($"{i} ");
}
// OUTPUT
رقم 1 ... رقم 5
count = 0, 1, 2
x = 10, 9
لغة: C#, Python, JavaScript
0 1 2 4 5
⚡ مبتدئ
06

المصفوفات (Arrays)

1D, 2D, Jagged Arrays — Collection Expressions (C# 12)

C# — المصفوفات
// ==============================
// 1D Arrays
// ==============================
int[] numbers  = { 10, 20, 30, 40 };
int[] zeros    = new int[5];    // [0,0,0,0,0]
int[] nums12   = [1, 2, 3];    // C# 12 Collection Expression

// الوصول والتعديل
Console.WriteLine(numbers[0]);   // 10
numbers[1] = 99;
Console.WriteLine(numbers.Length); // 4

// ==============================
// 2D Arrays
// ==============================
int[,] matrix = {
    { 1, 2, 3 },
    { 4, 5, 6 }
};
Console.WriteLine(matrix[1, 2]);  // 6

// ==============================
// Array Methods
// ==============================
int[] scores = { 85, 92, 71, 98, 65 };
Array.Sort(scores);
Array.Reverse(scores);
Console.WriteLine(string.Join(", ", scores));

// Index من النهاية (C# 8+)
Console.WriteLine(scores[^1]);   // آخر عنصر

// Range Slicing
int[] slice = scores[1..3];       // عناصر من 1 إلى 2
⚡ مبتدئ
07

الدوال (Methods)

Parameters, Return Types, Optional, ref, out, Expression Body

C# — الدوال بكل أنواعها
// ==============================
// دالة أساسية
// ==============================
static void Greet(string name)
{
    Console.WriteLine($"أهلاً {name}!");
}

// ==============================
// دالة تُرجع قيمة
// ==============================
static int Add(int a, int b) => a + b;  // Expression Body (مختصر)

// ==============================
// قيم افتراضية (Optional Parameters)
// ==============================
static string CreateUser(string name, int age = 18, string role = "user")
    => $"[{role}] {name} ({age})";

// ==============================
// ref & out
// ==============================
static void Swap(ref int a, ref int b)
{
    (a, b) = (b, a);  // Tuple Deconstruction
}

static bool TryParse(string input, out int result)
{
    return int.TryParse(input, out result);
}

// ==============================
// params — عدد متغير من الوسيط
// ==============================
static int Sum(params int[] nums) => nums.Sum();

// الاستخدام
Greet("Yahya");
Console.WriteLine(Add(5, 3));          // 8
Console.WriteLine(CreateUser("Ali"));   // [user] Ali (18)
Console.WriteLine(Sum(1, 2, 3, 4, 5)); // 15
// OUTPUT
أهلاً Yahya!
8
[user] Ali (18)
15
🎯

تطبيق عملي — نظام تقييم الطلاب

مستوى: أساسي

دمجت حتى الآن: المتغيرات، التحكم في التدفق، الحلقات، المصفوفات، والدوال. حان وقت تجميعها في برنامج Console واحد متكامل — بدون أي حل جاهز، فقط المواصفة:

  • أنشئ مصفوفة int[] بدرجات 5 طلاب (من 0 إلى 100).
  • اكتب دالة static string GetGrade(int score) تستخدم Switch Expression لتُرجع التقدير (A/B/C/D/F).
  • اطبع باستخدام foreach كل درجة وتقديرها المقابل.
  • اكتب دالة ثانية static double GetAverage(int[] scores) تحسب المتوسط وتطبعه.
  • التحدي الإضافي: اكتب دالة static int[] GetTopThree(int[] scores) تُرجع أعلى 3 درجات مرتّبة تنازلياً — بدون استخدام LINQ (لم نصل له بعد)، استخدم Array.Sort وArray.Reverse فقط.
🔍 ابحث عن:  "C# switch expression syntax" · "Array.Sort C# descending" · "C# static method return array"
🔥 متوسط
08

الكلاسات والكائنات

الأساس الحقيقي لـ C# — Class, Object, Constructor, Properties

البرمجة كائنية التوجه (OOP) هي قلب C#. تُنظّم الكود في وحدات (Classes) تحمل بيانات وسلوك.

C# — Class كاملة
// تعريف الكلاس
public class Developer
{
    // Properties (الخصائص)
    public string Name    { get; set; }
    public string Brand   { get; set; } = "Yahya.DEV";
    public int    YearsXP { get; private set; }

    // Field
    private string[] _skills;

    // Constructor الأساسي
    public Developer(string name, int years, string[] skills)
    {
        Name    = name;
        YearsXP = years;
        _skills  = skills;
    }

    // Primary Constructor (C# 12)
    // public Developer(string name) => Name = name;

    // Method
    public void Introduce()
    {
        Console.WriteLine($"🚀 {Name} | {Brand}");
        Console.WriteLine($"   خبرة: {YearsXP} سنوات");
        Console.WriteLine($"   مهارات: {string.Join(", ", _skills)}");
    }

    // Override ToString
    public override string ToString()
        => $"Developer: {Name} @ {Brand}";

    // Static Method
    public static Developer CreateJunior(string name)
        => new(name, 1, ["HTML", "CSS"]);
}

// الاستخدام
var dev = new Developer("Yahya", 3, ["C#", "Laravel", "JS"]);
dev.Introduce();
Console.WriteLine(dev);  // ToString

// Object Initializer Syntax
var dev2 = new Developer("Ali", 2, ["Python"])
{
    Brand = "AliDev"
};
// OUTPUT
🚀 Yahya | Yahya.DEV
خبرة: 3 سنوات
مهارات: C#, Laravel, JS
Developer: Yahya @ Yahya.DEV
🔥 متوسط
09

الوراثة والتغليف والتعدد

Inheritance, Encapsulation, Polymorphism — ركائز OOP

C# — OOP كاملاً
// ==============================
// الكلاس الأساسي (Base Class)
// ==============================
public abstract class Animal
{
    public string Name   { get; init; }
    public int    Age    { get; init; }

    protected Animal(string name, int age)
        => (Name, Age) = (name, age);

    // abstract: يجب على الـ SubClass تنفيذها
    public abstract void Speak();

    // virtual: يمكن للـ SubClass تجاوزها
    public virtual string Describe()
        => $"{Name} ({Age} سنوات)";
}

// ==============================
// Sub Classes
// ==============================
public class Dog : Animal
{
    public string Breed { get; init; }

    public Dog(string name, int age, string breed)
        : base(name, age) => Breed = breed;

    public override void Speak()
        => Console.WriteLine($"{Name}: Woof! 🐕");

    public override string Describe()
        => $"{base.Describe()} — {Breed}";
}

public class Cat : Animal
{
    public Cat(string name, int age) : base(name, age) { }
    public override void Speak()
        => Console.WriteLine($"{Name}: Meow! 🐈");
}

// ==============================
// Polymorphism
// ==============================
Animal[] animals =
[
    new Dog("Rex", 3, "Husky"),
    new Cat("Luna", 2),
    new Dog("Buddy", 5, "Lab")
];

foreach (var a in animals)
{
    a.Speak();
    Console.WriteLine($"  ↳ {a.Describe()}");
}
// OUTPUT
Rex: Woof! 🐕
↳ Rex (3 سنوات) — Husky
Luna: Meow! 🐈
↳ Luna (2 سنوات)
Buddy: Woof! 🐕
↳ Buddy (5 سنوات) — Lab
🔥 متوسط
10

الواجهات (Interfaces)

عقود البرمجة — الفرق بين Interface و Abstract Class

C# — Interfaces
// Interface = عقد: "من ينفّذني يجب أن يوفّر هذه الدوال"
public interface IPaymentGateway
{
    bool  ProcessPayment(decimal amount);
    string Name { get; }

    // Default Implementation (C# 8+)
    void LogTransaction(decimal amount)
        => Console.WriteLine($"[{Name}] معالجة: {amount:C}");
}

public interface IRefundable
{
    bool Refund(decimal amount);
}

// Class تنفّذ واجهتين
public class StripeGateway : IPaymentGateway, IRefundable
{
    public string Name => "Stripe";

    public bool ProcessPayment(decimal amount)
    {
        Console.WriteLine($"Stripe: دفع {amount:C} ✅");
        return true;
    }

    public bool Refund(decimal amount)
    {
        Console.WriteLine($"Stripe: استرداد {amount:C} 🔄");
        return true;
    }
}

// Dependency Injection مثال
void Checkout(IPaymentGateway gateway, decimal total)
{
    gateway.LogTransaction(total);
    gateway.ProcessPayment(total);
}

var stripe = new StripeGateway();
Checkout(stripe, 99.99m);
📌
Interface vs Abstract Class: استخدم Interface عندما تريد تعريف "قدرة" يمكن لأي كلاس اكتسابها. استخدم Abstract Class عندما يكون هناك كود مشترك بين الكلاسات المشتقة.
🪲 مطبات برمجية
🪲

مطبات برمجية — أساسيات OOP

NullReferenceException، نسيان override، وأخطاء الوصول

⚠️ NullReferenceException — أشهر استثناء في C#
Customer? customer = FindCustomer(99); // غير موجود، يرجع null Console.WriteLine(customer.Name);
System.NullReferenceException: 'Object reference not set to an instance of an object.'
Console.WriteLine(customer?.Name ?? "غير موجود");
السبب: الدالة أرجعت null لأنها لم تجد نتيجة، وحاولت الوصول لخاصية على متغير لا يشير لأي كائن حقيقي في Heap. الـ Nullable Reference Types في C# الحديثة تنبّهك لهذا أثناء الكتابة قبل التشغيل أصلاً.
⚠️ نسيان override فلا يُستدعى السلوك الجديد أبداً
class Animal { public virtual string Speak() => "صوت"; } class Dog : Animal { public string Speak() => "هواو"; // نسي override! } Animal a = new Dog(); Console.WriteLine(a.Speak()); // "صوت" — ليس "هواو"!
لا خطأ ترجمة — لكن CS0114 warning: 'Dog.Speak() hides inherited member. Use the new keyword if hiding was intended.'
public override string Speak() => "هواو";
السبب: بدون override، الدالة الجديدة "تخفي" الأصلية فقط (Method Hiding) ولا تستبدلها فعلياً — والاستدعاء عبر النوع الأساسي (Animal) يبقى يرى الدالة القديمة. هذا فرق دقيق ويُسقط الكثيرين.
⚠️ StackOverflowException من Recursion غير منتهٍ في الخصائص
private string name; public string Name { get => Name; // يستدعي نفسه! ليس name set => Name = value; // نفس المشكلة }
Process terminated. StackOverflowException
public string Name { get => name; set => name = value; } // أو أبسط: public string Name { get; set; }
السبب: الخاصية Name (بحرف كبير) تستدعي نفسها بدلاً من الحقل name (بحرف صغير) — كل استدعاء يضيف إطاراً جديداً على Stack حتى تمتلئ الذاكرة المخصصة له تماماً.
⚠️ محاولة الوصول لعضو private من كلاس مشتق
class Account { private decimal balance; } class SavingsAccount : Account { public void Show() => Console.WriteLine(balance); // ❌ }
CS0122: 'Account.balance' is inaccessible due to its protection level
class Account { protected decimal balance; // متاح للمشتقّات فقط }
السبب: private تعني "هذا الكلاس فقط، لا حتى أطفاله". إن أردت أن تصل الكلاسات المشتقة لعضو ما، استخدم protected — هذا الفرق هو جوهر مبدأ Encapsulation الصحيح.
🔥 متوسط
11

الـ Generics

كود يعمل مع أي نوع — Type Safety + Reusability

C# — Generics
// Generic Method
static T GetMax<T>(T a, T b) where T : IComparable<T>
    => a.CompareTo(b) > 0 ? a : b;

Console.WriteLine(GetMax(10, 25));          // 25
Console.WriteLine(GetMax("Apple", "Mango")); // Mango

// Generic Class — Stack بسيط
public class SimpleStack<T>
{
    private List<T> _items = [];

    public void Push(T item) => _items.Add(item);

    public T Pop()
    {
        if (_items.Count == 0)
            throw new InvalidOperationException("Stack فارغ!");
        var item = _items[^1];
        _items.RemoveAt(_items.Count - 1);
        return item;
    }

    public int Count => _items.Count;
}

var stack = new SimpleStack<int>();
stack.Push(1); stack.Push(2); stack.Push(3);
Console.WriteLine(stack.Pop());  // 3
🔥 متوسط
12

المجموعات (Collections)

List, Dictionary, HashSet, Queue, Stack

C# — Collections
// ==============================
// List<T> — المصفوفة الديناميكية
// ==============================
var names = new List<string> { "Yahya", "Ali", "Sara" };
names.Add("Omar");
names.Remove("Ali");
names.Sort();
Console.WriteLine(string.Join(", ", names));

// ==============================
// Dictionary<K, V> — جدول البحث
// ==============================
var scores = new Dictionary<string, int>
{
    ["C#"]         = 95,
    ["JavaScript"] = 88,
    ["Python"]     = 82
};

scores["Go"] = 75;  // إضافة جديد

foreach (var (lang, score) in scores)
    Console.WriteLine($"{lang}: {score}");

// ==============================
// HashSet<T> — بدون تكرار
// ==============================
var tags = new HashSet<string> { "dev", "ui", "dev" };
tags.Add("ux");
Console.WriteLine(tags.Count);  // 3 (dev لا يتكرر)

// ==============================
// Queue<T> — FIFO (أول داخل أول خارج)
// ==============================
var queue = new Queue<string>();
queue.Enqueue("Request 1");
queue.Enqueue("Request 2");
Console.WriteLine(queue.Dequeue());  // "Request 1"
🎯

تطبيق عملي — نظام مكتبة (Library Management)

مستوى: متوسط

الآن وقد امتلكت OOP الكاملة والـ Generics والـ Collections، ابنِ نظاماً حقيقياً صغيراً — هذا التمرين هو بروفة مباشرة لمشروع التخرّج القادم:

  • كلاس Book بخصائص: Title, Author, bool IsBorrowed.
  • كلاس Library يحتوي List<Book> داخلية (private)، مع دوال: AddBook, BorrowBook(string title), ReturnBook(string title).
  • استخدم Dictionary<string, Book> بدلاً من List إن أردت بحثاً أسرع بالعنوان — جرّب الفرق في الأداء بنفسك.
  • دالة ListAvailableBooks() تطبع فقط الكتب غير المستعارة حالياً.
  • التحدي الإضافي: اجعل BorrowBook تُطلق Exception مخصصة (BookNotAvailableException) إن كان الكتاب مستعاراً فعلاً، وتعامل معها بـ try/catch في نقطة الاستخدام.
🔍 ابحث عن:  "C# Dictionary TryGetValue" · "C# custom exception class" · "List vs Dictionary performance C#"
💎 متقدم
13

LINQ — اللغة المدمجة للاستعلامات

أقوى ميزة في C# — قدرة SQL داخل الكود

LINQ (Language Integrated Query) يتيح لك الاستعلام عن أي مجموعة بيانات (List, Array, Database, XML...) باستخدام نفس الصياغة الأنيقة.

C# — LINQ شامل
record Product(string Name, decimal Price, string Category);

var products = new List<Product>
{
    new("Laptop",   3500m, "Tech"),
    new("Mouse",    150m,  "Tech"),
    new("Desk",     800m,  "Furniture"),
    new("Chair",    1200m, "Furniture"),
    new("Keyboard", 250m,  "Tech")
};

// ==============================
// Method Syntax (الأكثر شيوعاً)
// ==============================

// Where — التصفية
var expensive = products
    .Where(p => p.Price > 500m)
    .OrderBy(p => p.Price);

// Select — التحويل
var names = products.Select(p => p.Name.ToUpper());

// GroupBy — التجميع
var byCategory = products
    .GroupBy(p => p.Category)
    .Select(g => new
    {
        Category = g.Key,
        Count    = g.Count(),
        AvgPrice = g.Average(p => p.Price)
    });

foreach (var cat in byCategory)
    Console.WriteLine($"{cat.Category}: {cat.Count} منتج، متوسط السعر {cat.AvgPrice:C}");

// Aggregate Functions
decimal total   = products.Sum(p => p.Price);
decimal maxPrice = products.Max(p => p.Price);
var     cheapest = products.MinBy(p => p.Price)!;

// ==============================
// Query Syntax (شبيه SQL)
// ==============================
var techItems =
    from p in products
    where p.Category == "Tech"
    orderby p.Price descending
    select $"{p.Name} — {p.Price:C}";

foreach (var item in techItems)
    Console.WriteLine(item);
// OUTPUT
Tech: 3 منتج، متوسط السعر 1,300.00
Furniture: 2 منتج، متوسط السعر 1,000.00
Laptop — 3,500.00
Keyboard — 250.00
Mouse — 150.00
💎 متقدم
14

Delegates, Lambda & Events

الدوال كقيم — الأساس الفلسفي للـ Functional Programming في C#

C# — Delegates, Func, Action, Events
// ==============================
// 1. Delegate — نوع يمثل دالة
// ==============================
delegate int MathOp(int a, int b);

MathOp add      = (a, b) => a + b;
MathOp multiply = (a, b) => a * b;

Console.WriteLine(add(5, 3));       // 8
Console.WriteLine(multiply(5, 3)); // 15

// ==============================
// 2. Func<T, TResult> (مدمج)
// ==============================
Func<int, int, int>  power  = (base_, exp) => (int)Math.Pow(base_, exp);
Func<string, string> upper  = s => s.ToUpper();
Action<string>        log    = msg => Console.WriteLine($"[LOG] {msg}");
Predicate<int>        isEven = n => n % 2 == 0;

Console.WriteLine(power(2, 10));  // 1024
log("تم تسجيل الدخول");
Console.WriteLine(isEven(7));     // False

// ==============================
// 3. Events — نظام الأحداث
// ==============================
public class Button
{
    public event Action<string>? Clicked;

    public void Click(string label)
    {
        Console.WriteLine($"تم النقر على: {label}");
        Clicked?.Invoke(label);
    }
}

var btn = new Button();
btn.Clicked += label => Console.WriteLine($"  → Handler 1: {label}");
btn.Clicked += label => Console.WriteLine($"  → Handler 2: تسجيل");
btn.Click("حفظ");
// OUTPUT
تم النقر على: حفظ
→ Handler 1: حفظ
→ Handler 2: تسجيل
💎 متقدم
15

Async / Await — البرمجة اللامتزامنة

أهم مفهوم للتطبيقات الحقيقية — API Calls, File IO, Database

Async/Await يجعل العمليات الطويلة (شبكة، قاعدة بيانات، ملفات) لا تُجمّد واجهة المستخدم أو الخادم.

C# — Async/Await شامل
using System.Net.Http;
using System.Text.Json;

// ==============================
// 1. دالة async أساسية
// ==============================
static async Task<string> FetchDataAsync(string url)
{
    using var client = new HttpClient();
    Console.WriteLine($"جاري الجلب: {url}");
    string data = await client.GetStringAsync(url);
    return data[..Math.Min(100, data.Length)]; // أول 100 حرف
}

// ==============================
// 2. تشغيل عمليات بالتوازي
// ==============================
static async Task RunParallelAsync()
{
    var task1 = SimulateWorkAsync("DB Query",   1000);
    var task2 = SimulateWorkAsync("API Call",   1500);
    var task3 = SimulateWorkAsync("File Read",  800);

    // ينتهي الثلاثة معاً (لا تنتظر واحداً تلو الآخر)
    await Task.WhenAll(task1, task2, task3);
    Console.WriteLine("✅ كل العمليات اكتملت!");
}

static async Task<string> SimulateWorkAsync(string name, int ms)
{
    Console.WriteLine($"بدأ: {name}");
    await Task.Delay(ms);
    Console.WriteLine($"انتهى: {name}");
    return name;
}

// ==============================
// 3. try/catch مع async
// ==============================
static async Task<bool> SafeFetchAsync(string url)
{
    try
    {
        var result = await FetchDataAsync(url);
        Console.WriteLine($"نجح: {result.Length} حرف");
        return true;
    }
    catch (HttpRequestException ex)
    {
        Console.WriteLine($"خطأ شبكة: {ex.Message}");
        return false;
    }
}

// تشغيل
await RunParallelAsync();
⚠️
تحذير: لا تستخدم .Result أو .Wait() على Task — يسبب Deadlock في تطبيقات UI وASP.NET. استخدم await دائماً.
💎 متقدم
16

معالجة الأخطاء (Exception Handling)

try/catch/finally, Custom Exceptions, Global Handler

C# — معالجة الأخطاء
// ==============================
// 1. try / catch / finally
// ==============================
try
{
    int[] arr = [1, 2, 3];
    Console.WriteLine(arr[10]); // IndexOutOfRangeException
}
catch (IndexOutOfRangeException ex)
{
    Console.WriteLine($"خطأ الفهرس: {ex.Message}");
}
catch (Exception ex) when (ex.Message.Contains("network"))
{
    Console.WriteLine("خطأ شبكة محدد");
}
catch (Exception ex)
{
    Console.WriteLine($"خطأ عام: {ex.GetType().Name}");
}
finally
{
    Console.WriteLine("✅ ينفّذ دائماً — للتنظيف");
}

// ==============================
// 2. Custom Exception
// ==============================
public class ValidationException : Exception
{
    public string Field { get; }

    public ValidationException(string field, string message)
        : base(message)
    {
        Field = field;
    }
}

static void ValidateAge(int age)
{
    if (age < 0 || age > 150)
        throw new ValidationException("age", $"العمر {age} غير صحيح");
}

try { ValidateAge(-5); }
catch (ValidationException ex)
{
    Console.WriteLine($"خطأ التحقق في [{ex.Field}]: {ex.Message}");
}
🪲 مطبات برمجية
🪲

مطبات برمجية — Async وException Handling

Deadlocks، async void، وCatch الصامت

⚠️ Deadlock من استخدام .Result أو .Wait()
public string GetData() { var task = FetchDataAsync(); return task.Result; // ⛔ يحظر الـ Thread الرئيسي }
يتجمّد البرنامج بلا أي رسالة خطأ — Deadlock صامت تماماً
public async Task<string> GetDataAsync() { return await FetchDataAsync(); // await لا يحظر الـ Thread }
السبب: .Result يوقف الـ Thread الحالي وينتظره بشكل متزامن (Blocking)، بينما المهمة غير المتزامنة قد تحتاج العودة لهذا الـ Thread نفسه لتكمل — فيحصل تعليق دائري. القاعدة: async طوال الطريق، لا تخلط بين Sync و Async.
⚠️ async void — استثناءات تختفي بلا أثر
async void SaveData() { throw new Exception("فشل الحفظ"); // لا أحد يستطيع الـ catch لهذا الاستثناء! }
البرنامج قد ينهار فجأة دون stack trace مفيد، أو الخطأ يُبتلع تماماً
async Task SaveDataAsync() { throw new Exception("فشل الحفظ"); } // عند الاستدعاء: await SaveDataAsync(); داخل try/catch
السبب: async void لا تُرجع Task يمكن انتظاره أو مراقبته — استثناءاتها لا تنتقل للمُستدعي بالطريقة العادية. استخدمها فقط لمعالجات الأحداث (Event Handlers)، وفي كل مكان آخر استخدم async Task.
⚠️ catch (Exception) فارغ يُخفي مشاكل حقيقية
try { ProcessOrder(order); } catch (Exception) { // فارغ تماماً — صمت كامل }
لا خطأ ظاهر — لكن الطلب لم يُعالَج فعلياً، والبرنامج "يبدو" سليماً
try { ProcessOrder(order); } catch (OrderValidationException ex) { Console.WriteLine($"خطأ تحقق: {ex.Message}"); } catch (Exception ex) { Console.WriteLine($"خطأ غير متوقع: {ex.Message}"); throw; // أعد إطلاقه إن لم تستطع التعامل معه فعلياً }
السبب: الإمساك بكل الاستثناءات بنوع عام دون أي تعامل حقيقي معها هو أخطر أنماط الأخطاء — يحوّل مشاكل حقيقية إلى سلوك صامت غير متوقَّع. أمسك بأنواع محدّدة قدر الإمكان، وسجِّل كل ما تمسكه.
🚀 خبير
17

Pattern Matching

ميزة C# 8-13 الأقوى — Type, Property, List Patterns

C# — Pattern Matching الشامل
// ==============================
// Type Pattern
// ==============================
static string Describe(object obj) => obj switch
{
    int    n  when n > 0 => $"عدد موجب: {n}",
    int    n              => $"عدد: {n}",
    string { Length: 0 } => "نص فارغ",
    string s              => $"نص: {s}",
    null                   => "null",
    _                      => $"نوع: {obj.GetType().Name}"
};

Console.WriteLine(Describe(42));     // عدد موجب: 42
Console.WriteLine(Describe("Dev"));  // نص: Dev

// ==============================
// Property Pattern
// ==============================
record Order(decimal Amount, string Status, bool IsPremium);

static decimal CalcDiscount(Order o) => o switch
{
    { IsPremium: true, Amount: > 1000m } => o.Amount * 0.20m,
    { IsPremium: true }                   => o.Amount * 0.10m,
    { Status: "VIP", Amount: > 500m }   => o.Amount * 0.15m,
    _                                       => 0m
};

var order = new Order(1500m, "Regular", true);
Console.WriteLine($"الخصم: {CalcDiscount(order):C}"); // 300.00

// ==============================
// List Pattern (C# 11)
// ==============================
static string CheckList(int[] arr) => arr switch
{
    []              => "فارغ",
    [var single]   => $"عنصر واحد: {single}",
    [var first, ..] => $"يبدأ بـ: {first}"
};

Console.WriteLine(CheckList([]));           // فارغ
Console.WriteLine(CheckList([7]));          // عنصر واحد: 7
Console.WriteLine(CheckList([1, 2, 3]));   // يبدأ بـ: 1
🚀 خبير
18

Records و Immutability

C# 9+ — بيانات ثابتة، مقارنة بالقيم، with expression

C# — Records
// ==============================
// Record (Positional) — أبسط طريقة
// ==============================
record Point(double X, double Y);

var p1 = new Point(3.0, 4.0);
var p2 = new Point(3.0, 4.0);
var p3 = p1 with { X = 10.0 };     // نسخة معدّلة

Console.WriteLine(p1 == p2);        // True  (مقارنة بالقيمة)
Console.WriteLine(p1);              // Point { X = 3, Y = 4 }
Console.WriteLine(p3);              // Point { X = 10, Y = 4 }

// ==============================
// Record Class (مفصّل)
// ==============================
public record User
{
    public required string Id    { get; init; }
    public required string Name  { get; init; }
    public          string Email { get; init; } = string.Empty;

    // يمكن إضافة methods
    public string GetDisplayName() => $"@{Name.ToLower()}";
}

var user = new User { Id = "1", Name = "Yahya", Email = "y@dev.com" };
Console.WriteLine(user.GetDisplayName());  // @yahya

// user.Name = "X"; ← خطأ! init-only

// ==============================
// Record Struct (C# 10) — Value Type
// ==============================
readonly record struct Color(byte R, byte G, byte B)
{
    public string Hex => $"#{R:X2}{G:X2}{B:X2}";
}

var purple = new Color(124, 58, 237);
Console.WriteLine(purple.Hex);  // #7C3AED
// OUTPUT
True
Point { X = 3, Y = 4 }
Point { X = 10, Y = 4 }
@yahya
#7C3AED
🚀 خبير
19

Nullable Reference Types & Null Safety

C# 8+ — القضاء على NullReferenceException

C# — Null Safety
// في .csproj: <Nullable>enable</Nullable>

string  name     = "Yahya";   // لا يقبل null
string? nickname = null;     // يقبل null (? = nullable)

// Null Conditional ?.
int? len = nickname?.Length;  // null بدل crash

// Null Coalescing ??
string display = nickname ?? "مجهول";

// Null Coalescing Assignment ??=
nickname ??= "Dev";  // يُعيّن فقط إذا كان null

// Null Forgiving ! (استخدم بحذر)
string guaranteed = nickname!;  // أنت مسؤول

// ==============================
// Pattern Matching مع Null
// ==============================
static void Process(string? value)
{
    if (value is null)
    {
        Console.WriteLine("القيمة null");
        return;
    }

    // هنا المترجم يعرف أن value ليست null
    Console.WriteLine(value.ToUpper());
}

// ==============================
// Required Properties (C# 11)
// ==============================
public class Config
{
    public required string ConnectionString { get; init; }
    public required string AppName          { get; init; }
    public          int    Timeout          { get; init; } = 30;
}

// خطأ وقت الترجمة إذا لم تُعيّن required:
var cfg = new Config
{
    ConnectionString = "Server=.;...",
    AppName          = "Yahya.DEV"
};
🚀 خبير
20

C# 13 — أحدث الميزات 2024/2025

params Collections, Lock, Escape Sequences, Partial Properties

C# 13 — .NET 9
// ==============================
// 1. params Collections (C# 13)
// ==============================
// قبل C#13: فقط params int[] arr
// الآن يدعم List, Span, IEnumerable وغيرها
static int Sum(params IEnumerable<int> numbers)
    => numbers.Sum();

Console.WriteLine(Sum(1, 2, 3, 4, 5));      // 15
Console.WriteLine(Sum([10, 20, 30]));       // 60

// ==============================
// 2. New Lock Type (C# 13)
// ==============================
// أفضل من lock(object) القديم
var lockObj = new System.Threading.Lock();

lock (lockObj)
{
    Console.WriteLine("عملية thread-safe ✅");
}

// ==============================
// 3. Escape Sequence \e (C# 13)
// ==============================
// \e = ESC character (ASCII 27) للـ terminal colors
Console.WriteLine("\e[32mنص أخضر في الـ terminal\e[0m");

// ==============================
// 4. Primary Constructors (C# 12 - شائع جداً)
// ==============================
public class ApiService(HttpClient httpClient, string baseUrl)
{
    public async Task<string> GetAsync(string endpoint)
        => await httpClient.GetStringAsync($"{baseUrl}/{endpoint}");
}

// ==============================
// 5. Collection Expressions (C# 12)
// ==============================
int[]            arr   = [1, 2, 3];
List<string>     list  = ["a", "b"];
Span<int>         span  = [10, 20];

// Spread operator ..
int[] combined = [..arr, 4, 5, 6]; // [1,2,3,4,5,6]

// ==============================
// 6. Inline Arrays (C# 12) — للأداء
// ==============================
[System.Runtime.CompilerServices.InlineArray(10)]
public struct Buffer10
{
    private int _element;  // 10 int على الـ stack
}
params IEnumerable System.Threading.Lock Collection Expressions Primary Constructors Spread Operator .. Inline Arrays \e Escape
🚀
الخطوة التالية: بعد إتقان هذا الدليل، تعمّق في: ASP.NET Core لبناء APIs، أو Unity لتطوير الألعاب، أو .NET MAUI لتطبيقات الجوال.
🏗️ مشروع التخرّج
21

مقدّمة المشروع — نظام يحيى لإدارة المهام (نسخة Console)

تطبيق كل أدوات الكورس في مشروع واحد منظَّم بانضباط هندسي حقيقي

هذا المشروع يجمع كل ما تعلّمته: Records، Enums، Interfaces، Generics/Collections، LINQ، وException Handling — في تطبيق Console واحد منظَّم بطبقات واضحة (Models / Repositories / Services).

المبدأ المحوري هنا هو Repository Pattern: نخفي "كيف تُخزَّن البيانات" خلف Interface ثابت. اليوم التخزين في ملف JSON — وعندما تبدأ دبلومة Backend .NET وتتعلّم Entity Framework Core، ستستبدل JsonTaskRepository بـ EfTaskRepository يتصل بقاعدة بيانات حقيقية — بنفس الـ Interface تماماً، دون تعديل أي كود آخر في المشروع.
📁TaskManagerConsole/ ├── 📁Models/ │ └── TaskItem.cs ← القسم 22 ├── 📁Repositories/ │ ├── ITaskRepository.cs ← القسم 22 │ └── JsonTaskRepository.cs ← القسم 22 ├── 📁Services/ │ └── TaskService.cs ← القسم 23 ├── Program.cs ← القسم 23 — قائمة Console └── tasks.json ← يُنشأ تلقائياً عند أول تشغيل
📌
مواصفات المشروع: إضافة مهمة بعنوان ووصف وأولوية، عرض القائمة مرتّبة حسب الأولوية، تعليم مهمة كمكتملة، حذف مهمة — مع تحقق من المدخلات ومعالجة استثناءات سليمة.
🏗️ مشروع التخرّج
22

المشروع: البنية والنماذج

Record Model · Enum · Interface · JSON Repository

Models/TaskItem.cs
namespace TaskManagerConsole.Models;

public enum TaskPriority { Low, Medium, High }

// Record — نوع غير قابل للتعديل (Immutable)، مثالي لتمثيل بيانات ثابتة
public record TaskItem(
    int Id,
    string Title,
    string Description,
    TaskPriority Priority,
    bool IsDone = false
);
💡
لماذا record لا class؟ المهمة هنا "بيانات" أكثر من "سلوك معقّد". الـ record يعطينا مساواة بالقيمة (Value Equality) تلقائياً، وطريقة with لإنشاء نسخة معدَّلة دون تغيير الأصل — ستراها في المستودع بالأسفل.
Repositories/ITaskRepository.cs
namespace TaskManagerConsole.Repositories;

using TaskManagerConsole.Models;

public interface ITaskRepository
{
    List<TaskItem> GetAll();
    TaskItem? GetById(int id);
    void Add(TaskItem task);
    void MarkDone(int id);
    void Delete(int id);
}
📌
هذا الملف هو التعاقد الثابت الذي لن يتغيّر حتى عند ربط المشروع بـ EF Core لاحقاً — فقط الكلاس الذي ينفّذه سيتغيّر.
Repositories/JsonTaskRepository.cs
namespace TaskManagerConsole.Repositories;

using System.Text.Json;
using TaskManagerConsole.Models;

public class JsonTaskRepository : ITaskRepository
{
    private readonly string _path;
    private List<TaskItem> _tasks;

    public JsonTaskRepository(string path)
    {
        _path = path;
        _tasks = File.Exists(path)
            ? JsonSerializer.Deserialize<List<TaskItem>>(File.ReadAllText(path)) ?? new()
            : new List<TaskItem>();
    }

    public List<TaskItem> GetAll() => _tasks;

    public TaskItem? GetById(int id) =>
        _tasks.FirstOrDefault(t => t.Id == id);

    public void Add(TaskItem task) { _tasks.Add(task); Save(); }

    public void MarkDone(int id)
    {
        var index = _tasks.FindIndex(t => t.Id == id);
        if (index >= 0)
            _tasks[index] = _tasks[index] with { IsDone = true }; // نسخة معدَّلة، الأصل ثابت
        Save();
    }

    public void Delete(int id) { _tasks.RemoveAll(t => t.Id == id); Save(); }

    private void Save() =>
        File.WriteAllText(_path,
            JsonSerializer.Serialize(_tasks, new JsonSerializerOptions { WriteIndented = true }));
}
🏗️ مشروع التخرّج
23

المشروع: منطق العمل وقائمة Console

TaskService بالتحقق والـ LINQ، وProgram.cs بالقائمة التفاعلية

Services/TaskService.cs
namespace TaskManagerConsole.Services;

using TaskManagerConsole.Models;
using TaskManagerConsole.Repositories;

public class TaskService
{
    private readonly ITaskRepository _repo;

    public TaskService(ITaskRepository repo) => _repo = repo;

    public TaskItem CreateTask(string title, string description, TaskPriority priority)
    {
        if (string.IsNullOrWhiteSpace(title) || title.Length < 3)
            throw new ArgumentException("العنوان يجب أن يكون 3 أحرف على الأقل");

        var tasks = _repo.GetAll();
        var nextId = tasks.Count > 0 ? tasks.Max(t => t.Id) + 1 : 1;

        var task = new TaskItem(nextId, title, description, priority);
        _repo.Add(task);
        return task;
    }

    // LINQ — ترتيب حسب الأولوية تنازلياً
    public List<TaskItem> GetSortedByPriority() =>
        _repo.GetAll()
             .OrderByDescending(t => t.Priority)
             .ThenBy(t => t.IsDone)
             .ToList();
}
Program.cs — القائمة التفاعلية
using TaskManagerConsole.Models;
using TaskManagerConsole.Repositories;
using TaskManagerConsole.Services;

ITaskRepository repo = new JsonTaskRepository("tasks.json");
var service = new TaskService(repo);

while (true)
{
    Console.WriteLine("\n1) إضافة  2) عرض الكل  3) إكمال  4) حذف  0) خروج");
    var choice = Console.ReadLine();

    try
    {
        switch (choice)
        {
            case "1":
                Console.Write("العنوان: ");
                var title = Console.ReadLine() ?? "";
                service.CreateTask(title, "", TaskPriority.Medium);
                Console.WriteLine("تمت الإضافة ✓");
                break;

            case "2":
                foreach (var t in service.GetSortedByPriority())
                    Console.WriteLine($"[{t.Id}] {t.Title} — {t.Priority} {(t.IsDone ? "" : "")}");
                break;

            case "0": return;
        }
    }
    catch (ArgumentException ex)
    {
        Console.WriteLine($"خطأ: {ex.Message}");
    }
}
💡
انظر كم أصبح Program.cs بسيطاً — لأن كل المنطق الثقيل (التحقق، الترتيب، التخزين) موجود في طبقات منفصلة. هذا الفرق العملي بين "كود يعمل" و"كود قابل للنمو والاختبار" — تماماً ما تحتاجه قبل دخول عالم Backend الحقيقي.
🏁

التحدي النهائي — اختبار استقلالك الكامل

بدون أي حل جاهز

وسّع مشروعك بنفسك بالكامل — بدون كود جاهز هنا، فقط المواصفة. الهدف قياس صادق لما امتلكته فعلاً:

  • تعديل مهمة (Update): أضف void Update(TaskItem task) في الـ Interface وفي JsonTaskRepository — فكّر: كيف تستخدم record with هنا أيضاً؟
  • تصنيفات (Category): أضف enum TaskCategory { Work, Personal, Study } كخاصية جديدة في TaskItem.
  • فلترة بـ LINQ: أضف دالة GetByCategory(TaskCategory category) في TaskService تستخدم .Where().
  • إحصائيات: دالة GetStats() تُرجع عدد المهام المكتملة وغير المكتملة باستخدام .Count() من LINQ.
  • اختبار الفهم الحقيقي: لو استبدلت JsonTaskRepository بالكامل بكلاس آخر، كم سطراً ستحتاج لتعديله في Program.cs أو TaskService؟ إن كان الجواب "صفر"، فقد نجحت في الهدف الحقيقي من هذا المشروع.
🔍 ابحث عن:  "C# record with expression" · "LINQ Where Count" · "C# enum as class property"
★ مرجع سريع

مرجع سريع — C# و OOP

Cheatsheet مكثَّف لأكثر ما ستحتاجه يومياً

الفئةالعنصرالاستخدام السريع
🧱 OOPclass vs recordrecord لبيانات ثابتة بمساواة قيمة، class لسلوك متغيّر
🧱 OOPinterfaceتعاقد سلوك بدون تنفيذ — أساس قابلية الاستبدال
🧱 OOPvirtual / overrideالسماح بإعادة تعريف سلوك في كلاس مشتق
🧱 OOPabstractكلاس لا يُنشأ مباشرة، يفرض تنفيذ أعضائه على المشتقّات
📦 CollectionsList<T>قائمة مرتّبة قابلة للتغيير
📦 CollectionsDictionary<K,V>بحث فوري بمفتاح — الأسرع للوصول العشوائي
🔍 LINQ.Where(x => ...)تصفية بشرط
🔍 LINQ.OrderByDescending(x => ...)ترتيب تنازلي
🔍 LINQ.FirstOrDefault(x => ...)أول عنصر مطابق أو null/default
🔍 LINQ.Select(x => ...)تحويل كل عنصر لشكل جديد
⚡ Asyncasync Taskدالة غير متزامنة قابلة للانتظار والمعالجة
⚡ Asyncawaitانتظار غير حاظر للـ Thread
🛟 Null Safety??قيمة افتراضية إن كانت null
🛟 Null Safety?.استدعاء آمن — null بدل Exception
⚠️ Errorstry / catch / finallyالتعامل مع الأخطاء بأناقة
⚠️ Errorsthrow new ArgumentException()رفض مدخلات غير صالحة بوضوح
🎓
الخطوة التالية في رحلتك: أنت الآن جاهز فعلاً لدبلومة Backend .NET — ستتعلّم ASP.NET Core لبناء REST APIs حقيقية، Entity Framework Core للتعامل مع قواعد البيانات، وDependency Injection. ولاحظ: نفس مبدأ Repository Pattern الذي بنيته هنا بالضبط هو ما ستستخدمه هناك — فقط بدّل JSON بقاعدة بيانات حقيقية.