ما هي لغة C#؟
نظرة شاملة — التاريخ، الاستخدامات، لماذا C# في 2026؟
C# (سي شارب) هي لغة برمجة حديثة متعددة الأغراض، طوّرتها شركة Microsoft عام 2000 بقيادة المهندس Anders Hejlsberg (مؤلف Turbo Pascal وDelphi). تعمل على إطار .NET وتُعدّ اليوم من أقوى اللغات وأكثرها توظيفاً في العالم.
- 🎮 تطوير الألعاب — Unity (المحرك الأشهر في العالم) يعتمد C# بالكامل
- 🌐 تطوير الويب — ASP.NET Core لبناء APIs وتطبيقات ويب سريعة
- 📱 تطبيقات الموبايل — .NET MAUI لـ iOS وAndroid
- 🖥️ تطبيقات سطح المكتب — WPF وWinForms وMAUI
- ☁️ الـ Cloud والـ Microservices — Azure-native
- 🤖 الذكاء الاصطناعي والـ ML — ML.NET
// أول برنامج 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("مرحباً بالعالم!"); } }
تاريخ اليوم: 30/05/2026
| إصدار | سنة الإصدار | أبرز الميزات |
|---|---|---|
| C# 1.0 | 2002 | البداية مع .NET Framework |
| C# 3.0 | 2007 | LINQ, Lambda, var |
| C# 5.0 | 2012 | async / await |
| C# 8.0 | 2019 | Nullable, Switch Expressions |
| C# 10.0 | 2021 | Global using, File-scoped namespace |
| C# 12.0 | 2023 | Primary Constructors, Collection Expressions |
| C# 13.0 | 2024/2025 | params collections, Lock type, escape sequences |
بيئة العمل وأول برنامج
Visual Studio, VS Code, .NET CLI — كيف تبدأ فوراً
- 🔵 Visual Studio 2022 — البيئة الأقوى (Windows / Mac) — مجاني للأفراد
- ⚡ VS Code + C# Extension — خفيف وسريع — يعمل على كل الأنظمة
- 🌐 dotnet.microsoft.com/fiddle — مباشرة في المتصفح بدون تثبيت
# تثبيت .NET 9 SDK أولاً من: https://dotnet.microsoft.com/download # إنشاء مشروع Console dotnet new console -n MyProject # الدخول للمجلد cd MyProject # تشغيل البرنامج dotnet run
العقلية الخلفية: كيف تُنفَّذ أكوادك فعلياً؟
Compilation → IL → CLR → JIT، وStack vs Heap
قبل أن تكتب سطراً واحداً آخر، يجب أن تفهم سؤالاً جوهرياً: عندما تضغط Run، ماذا يحدث بالضبط بين كتابتك للكود وظهور النتيجة على الشاشة؟ هذا الفهم هو ما يفرّق بين من "يحفظ الصيغ" ومن يفهم اللغة فعلياً.
1. كودك C#
ملفات .cs التي تكتبها بنفسك
2. مترجم Roslyn
يحوّل الكود إلى IL (لغة وسيطة، ليست لغة المعالج)
3. Assembly (.dll)
ملف يحتوي IL + بيانات وصفية (Metadata)
4. CLR + JIT
عند التشغيل، JIT يحوّل IL لتعليمات معالج حقيقية
كل متغير في برنامجك يعيش في مكان واحد من اثنين، وهذا يحدّد سلوكه بالكامل:
| الخاصية | Stack (المكدّس) | Heap (الكومة) |
|---|---|---|
| من يعيش هنا؟ | Value Types: int, double, bool, struct | Reference Types: class, string, array, object |
| السرعة | سريع جداً — تنظيم تلقائي صارم | أبطأ نسبياً — يحتاج تتبّعاً |
| التنظيف | يُحذف فوراً عند خروج الدالة | يُنظَّفه Garbage Collector لاحقاً |
| ما يحمله المتغير | القيمة الفعلية مباشرة | مرجع (Reference) يشير لموقع البيانات في Heap |
// 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 أيضاً!
99
المتغيرات والأنواع
كل أنواع البيانات في C# — Value Types vs Reference Types
في C# كل متغير له نوع محدد. اللغة strongly-typed — أي المُترجم يتحقق من الأنواع قبل التشغيل.
// ============================== // 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);
| النوع | الحجم | المدى | مثال |
|---|---|---|---|
| int | 4 bytes | ±2.1 مليار | int x = 42; |
| long | 8 bytes | ±9.2 كوينتيليون | long y = 9L; |
| double | 8 bytes | ±1.8×10³⁰⁸ | double d = 3.14; |
| decimal | 16 bytes | ±7.9×10²⁸ | decimal m = 9.99m; |
| bool | 1 byte | true / false | bool b = true; |
| char | 2 bytes | Unicode | char c = 'A'; |
| string | متغير | نص غير محدود | string s = "hi"; |
العمليات والتحكم في التدفق
if, else, switch, Ternary operator
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)
ناجح ✅
التقدير: B
الحلقات (Loops)
for, while, do-while, foreach
// ============================== // 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} "); }
count = 0, 1, 2
x = 10, 9
لغة: C#, Python, JavaScript
0 1 2 4 5
المصفوفات (Arrays)
1D, 2D, Jagged Arrays — Collection Expressions (C# 12)
// ============================== // 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
الدوال (Methods)
Parameters, Return Types, Optional, ref, out, Expression Body
// ============================== // دالة أساسية // ============================== 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
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# — Class, Object, Constructor, Properties
البرمجة كائنية التوجه (OOP) هي قلب C#. تُنظّم الكود في وحدات (Classes) تحمل بيانات وسلوك.
// تعريف الكلاس 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" };
خبرة: 3 سنوات
مهارات: C#, Laravel, JS
Developer: Yahya @ Yahya.DEV
الوراثة والتغليف والتعدد
Inheritance, Encapsulation, Polymorphism — ركائز 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()}"); }
↳ Rex (3 سنوات) — Husky
Luna: Meow! 🐈
↳ Luna (2 سنوات)
Buddy: Woof! 🐕
↳ Buddy (5 سنوات) — Lab
الواجهات (Interfaces)
عقود البرمجة — الفرق بين Interface و Abstract Class
// 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);
مطبات برمجية — أساسيات OOP
NullReferenceException، نسيان override، وأخطاء الوصول
الـ Generics
كود يعمل مع أي نوع — Type Safety + Reusability
// 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
المجموعات (Collections)
List, Dictionary, HashSet, Queue, Stack
// ============================== // 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 في نقطة الاستخدام.
LINQ — اللغة المدمجة للاستعلامات
أقوى ميزة في C# — قدرة SQL داخل الكود
LINQ (Language Integrated Query) يتيح لك الاستعلام عن أي مجموعة بيانات (List, Array, Database, XML...) باستخدام نفس الصياغة الأنيقة.
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);
Furniture: 2 منتج، متوسط السعر 1,000.00
Laptop — 3,500.00
Keyboard — 250.00
Mouse — 150.00
Delegates, Lambda & Events
الدوال كقيم — الأساس الفلسفي للـ Functional Programming في C#
// ============================== // 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("حفظ");
→ Handler 1: حفظ
→ Handler 2: تسجيل
Async / Await — البرمجة اللامتزامنة
أهم مفهوم للتطبيقات الحقيقية — API Calls, File IO, Database
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 دائماً.معالجة الأخطاء (Exception Handling)
try/catch/finally, Custom Exceptions, Global Handler
// ============================== // 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 الصامت
.Result يوقف الـ Thread الحالي وينتظره بشكل متزامن (Blocking)، بينما المهمة غير المتزامنة قد تحتاج العودة لهذا الـ Thread نفسه لتكمل — فيحصل تعليق دائري. القاعدة: async طوال الطريق، لا تخلط بين Sync و Async.async void لا تُرجع Task يمكن انتظاره أو مراقبته — استثناءاتها لا تنتقل للمُستدعي بالطريقة العادية. استخدمها فقط لمعالجات الأحداث (Event Handlers)، وفي كل مكان آخر استخدم async Task.Pattern Matching
ميزة C# 8-13 الأقوى — Type, Property, List Patterns
// ============================== // 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
Records و Immutability
C# 9+ — بيانات ثابتة، مقارنة بالقيم، with expression
// ============================== // 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
Point { X = 3, Y = 4 }
Point { X = 10, Y = 4 }
@yahya
#7C3AED
Nullable Reference Types & Null Safety
C# 8+ — القضاء على NullReferenceException
// في .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" };
C# 13 — أحدث الميزات 2024/2025
params Collections, Lock, Escape Sequences, Partial Properties
// ============================== // 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 }
مقدّمة المشروع — نظام يحيى لإدارة المهام (نسخة Console)
تطبيق كل أدوات الكورس في مشروع واحد منظَّم بانضباط هندسي حقيقي
هذا المشروع يجمع كل ما تعلّمته: Records، Enums، Interfaces، Generics/Collections، LINQ، وException Handling — في تطبيق Console واحد منظَّم بطبقات واضحة (Models / Repositories / Services).
JsonTaskRepository بـ EfTaskRepository يتصل بقاعدة بيانات حقيقية — بنفس الـ Interface تماماً، دون تعديل أي كود آخر في المشروع.المشروع: البنية والنماذج
Record Model · Enum · Interface · JSON Repository
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 );
with لإنشاء نسخة معدَّلة دون تغيير الأصل — ستراها في المستودع بالأسفل.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); }
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 })); }
المشروع: منطق العمل وقائمة Console
TaskService بالتحقق والـ LINQ، وProgram.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(); }
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}"); } }
التحدي النهائي — اختبار استقلالك الكامل
بدون أي حل جاهزوسّع مشروعك بنفسك بالكامل — بدون كود جاهز هنا، فقط المواصفة. الهدف قياس صادق لما امتلكته فعلاً:
- تعديل مهمة (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# و OOP
Cheatsheet مكثَّف لأكثر ما ستحتاجه يومياً
| الفئة | العنصر | الاستخدام السريع |
|---|---|---|
| 🧱 OOP | class vs record | record لبيانات ثابتة بمساواة قيمة، class لسلوك متغيّر |
| 🧱 OOP | interface | تعاقد سلوك بدون تنفيذ — أساس قابلية الاستبدال |
| 🧱 OOP | virtual / override | السماح بإعادة تعريف سلوك في كلاس مشتق |
| 🧱 OOP | abstract | كلاس لا يُنشأ مباشرة، يفرض تنفيذ أعضائه على المشتقّات |
| 📦 Collections | List<T> | قائمة مرتّبة قابلة للتغيير |
| 📦 Collections | Dictionary<K,V> | بحث فوري بمفتاح — الأسرع للوصول العشوائي |
| 🔍 LINQ | .Where(x => ...) | تصفية بشرط |
| 🔍 LINQ | .OrderByDescending(x => ...) | ترتيب تنازلي |
| 🔍 LINQ | .FirstOrDefault(x => ...) | أول عنصر مطابق أو null/default |
| 🔍 LINQ | .Select(x => ...) | تحويل كل عنصر لشكل جديد |
| ⚡ Async | async Task | دالة غير متزامنة قابلة للانتظار والمعالجة |
| ⚡ Async | await | انتظار غير حاظر للـ Thread |
| 🛟 Null Safety | ?? | قيمة افتراضية إن كانت null |
| 🛟 Null Safety | ?. | استدعاء آمن — null بدل Exception |
| ⚠️ Errors | try / catch / finally | التعامل مع الأخطاء بأناقة |
| ⚠️ Errors | throw new ArgumentException() | رفض مدخلات غير صالحة بوضوح |