البرمجة الوظيفية في لغة C#: المستوى المتقدم
البرمجة الوظيفية (FP) هي نموذج برمجي يتسلل بنشاط إلى عالم C# في السنوات الأخيرة. بفضل إمكانيات .NET، يمكن للمطورين الجمع بين المنهجيات الكائنية والوظيفية، مما ينتج كودًا أكثر موثوقية وقابلية للاختبار وقابلية للتنبؤ. في هذه المقالة، سنستكشف تقنيات البرمجة الوظيفية المتقدمة في C# التي ستساعدك على تجاوز مجرد استخدام LINQ البسيط.
1. الدوال النقية والتأثيرات الجانبية: تحكم صارم
الدالة النقية هي دالة تعتمد نتيجتها فقط على وسائط الإدخال الخاصة بها ولا تسبب أي تأثيرات جانبية (تعديل حالة شاملة، إدخال/إخراج، استثناءات). في C#، يمكننا الاقتراب من هذه المثالية باستخدام الأنواع غير القابلة للتغيير وتجنب تعديل المعاملات.
// دالة نقية: النتيجة تعتمد فقط على x و ypublic static int Add(int x, int y) => x + y;
// دالة غير نقية: تعتمد على حالة خارجيةprivate static int _counter = 0;public static int IncrementCounter() => ++_counter;على المستوى المتقدم، من المهم الفصل بشكل صارم بين العمليات الحسابية النقية والعمليات ذات التأثيرات الجانبية. لهذا، يمكنك استخدام نمط IO (في اللغات الوظيفية) أو نظائره المبسطة في C# عبر Func<T> والتقييم الكسول.
تقنية عملية: "التنفيذ الكسول"
بدلاً من تنفيذ إجراء ذي تأثير جانبي فورًا، قم بإرجاع مفوض سيقوم بتنفيذه:
public static Func<int> CreateFileReadOperation(string path){ return () => File.ReadAllText(path).Length; // التأثير الجانبي مؤجل}
// الاستخدامvar operation = CreateFileReadOperation("data.txt");// ... منطق نقي ...int length = operation(); // يتم تنفيذ التأثير الجانبي هنا2. تركيب الدوال والكاري
التركيب هو دمج دالتين أو أكثر لإنشاء دالة جديدة. الكاري هو تحويل دالة ذات عدة وسائط إلى سلسلة من الدوال ذات وسيط واحد. هذه التقنيات تجعل الكود أكثر نمطية وقابلية لإعادة الاستخدام.
التركيب عبر LINQ والطرق المخصصة
في C#، يمكن تنفيذ التركيب باستخدام طرق التمديد:
public static class FuncExtensions{ public static Func<T, TResult> Compose<T, TIntermediate, TResult>( this Func<T, TIntermediate> first, Func<TIntermediate, TResult> second) => x => second(first(x));}
// مثال: f(x) = x + 2, g(x) = x * 3, h = f ∘ gFunc<int, int> addTwo = x => x + 2;Func<int, int> multiplyByThree = x => x * 3;var composed = multiplyByThree.Compose(addTwo); // h(x) = (x*3) + 2Console.WriteLine(composed(5)); // 17الكاري في C#
الكاري يسمح بالتطبيق الجزئي للدالة:
public static Func<int, Func<int, int>> CurriedAdd = x => y => x + y;
var addFive = CurriedAdd(5); // تطبيق جزئيConsole.WriteLine(addFive(10)); // 15
// مثال أكثر تعقيدًا: دالة تسجيل مع بادئةpublic static Func<string, Func<string, string>> CreateLogger = prefix => message => $"[{prefix}] {message}";
var infoLogger = CreateLogger("INFO");Console.WriteLine(infoLogger("System started")); // [INFO] System started3. المونادات والعمل مع Option (Maybe)
الموناد هو نمط يسمح بتطبيق الدوال بشكل تسلسلي على قيم مغلفة في سياق (مثل إمكانية غياب القيمة أو التزامن). في C#، يحظى تطبيق Option<T> أو Maybe<T> بشعبية لتجنب null.
تطبيق بسيط لـ Option
public class Option<T>{ private readonly T _value; private readonly bool _hasValue;
pri