البرمجة الوظيفية في C#: من الألف إلى الياء
البرمجة الوظيفية (FP) هي نموذج برمجي يعتبر العمليات الحسابية كحساب للدوال الرياضية ويتجنب الحالة القابلة للتغيير والآثار الجانبية. على الرغم من أن C# هي لغة متعددة النماذج مع دعم قوي للبرمجة الشيئية (OOP)، إلا أن إصداراتها الحديثة (بدءًا من C# 3.0 فصاعدًا) تدمج بنشاط عناصر الأسلوب الوظيفي. وهذا يسمح بكتابة كود أكثر إيجازًا وقابلية للتنبؤ وسهولة في الاختبار.
في هذه المقالة، سننتقل من الأساسيات إلى التقنيات المتقدمة للبرمجة الوظيفية في C# في سياق .NET. ستتعلم كيفية استخدام تعبيرات لامدا، LINQ، أنواع البيانات غير القابلة للتغيير والأنماط لبناء تطبيقات موثوقة.
1. الأساسيات: تعبيرات لامدا والمفوضون
قلب النهج الوظيفي في C# هو تعبيرات لامدا — وهي دوال مجهولة يمكن استخدامها لإنشاء مفوضين أو أشجار تعبير. إنها تسمح بتمرير السلوك كبيانات.
لنأخذ مثالًا كلاسيكيًا لفرز قائمة. بدلاً من إنشاء طريقة مقارنة منفصلة، نستخدم لامدا:
using System;using System.Collections.Generic;
public class LambdaExample{ public static void Main() { var numbers = new List<int> { 5, 3, 8, 1, 9 }; // الفرز تنازليًا باستخدام تعبير لامدا numbers.Sort((x, y) => y.CompareTo(x)); Console.WriteLine(string.Join(", ", numbers)); // الإخراج: 9, 8, 5, 3, 1 }}المفاهيم الأساسية التي تعمل هنا:
- المفوضون
Func<>وAction<>:Func<T, TResult>يُرجع قيمة،Action<T>لا يُرجع. يتم تحويل تعبيرات لامدا ضمنيًا إلى هذه الأنواع. - الإغلاقات (Closures): يمكن للامدا التقاط متغيرات من النطاق الخارجي، مما يجعلها أداة قوية، ولكنها تتطلب الحذر بسبب الآثار الجانبية المحتملة.
2. LINQ: الأسلوب التصريحي للعمل مع البيانات
استعلام اللغة المتكامل (LINQ) هو ربما أبرز مثال على تطبيق البرمجة الوظيفية في C#. يسمح بكتابة استعلامات تصريحية للمجموعات، قواعد البيانات و XML، باستخدام سلاسل من الأساليب.
بدلاً من حلقات foreach الأمرية، نستخدم عمليات وظيفية:
using System;using System.Linq;using System.Collections.Generic;
public class LinqExample{ public static void Main() { var people = new List<Person> { new Person { Name = "Alice", Age = 30 }, new Person { Name = "Bob", Age = 17 }, new Person { Name = "Charlie", Age = 25 } };
// استعلام وظيفي: تصفية، إسقاط، فرز var result = people .Where(p => p.Age >= 18) // التصفية (المسند) .OrderBy(p => p.Name) // الفرز .Select(p => new { p.Name, IsAdult = true }) // الإسقاط (نوع مجهول) .ToList();
foreach (var item in result) { Console.WriteLine($"{item.Name} - Adult: {item.IsAdult}"); } // الإخراج: Alice - Adult: True, Charlie - Adult: True }
public class Person { public string Name { get; set; } public int Age { get; set; } }}عوامل LINQ الرئيسية:
Where— التصفية (مشابه لـfilter).Select— التحويل (مشابه لـmap).Aggregate— الطي (مشابه لـreduce).Any,All— التحقق من الشروط.
من المهم تذكر التنفيذ المؤجل