OneOf في C# (.NET): دليل شامل مع أمثلة تطبيقية
مكتبة OneOf هي تطبيق للاتحادات المميزة (Discriminated Unions) في لغة C#. تحل مشكلة أساسية: كيف يمكن تمثيل قيمة قد تكون من عدة أنواع معروفة مسبقًا بطريقة أنيقة في لغة ذات كتابة ثابتة. بدلاً من استخدام object مع تحويل الأنواع، أو Nullable، أو إنشاء تسلسلات هرمية للفئات، توفر OneOf طريقة آمنة من حيث النوع ومعبرة للعمل مع هذه القيم.
لماذا تحتاج إليها؟ أولاً، تزيد من قابلية قراءة الكود: التوقيع الذي يُرجع OneOf<Success, Error> يخبرك فورًا أن العملية قد تنجح أو تفشل. ثانيًا، تقضي على فئة كاملة من الأخطاء المتعلقة بتحويل الأنواع الخاطئ. ثالثًا، تجبر OneOf المطور على معالجة جميع الاحتمالات الممكنة، مما يجعل الكود أكثر موثوقية وقابلية للتنبؤ. هذا مفيد بشكل خاص في السيناريوهات التي تُستخدم فيها الاستثناءات تقليديًا (للتحكم في التدفق) أو إرجاع null.
تتناسب OneOf بشكل مثالي مع أسلوب البرمجة الوظيفية في C#. تتيح لك نمذجة مجال المشكلة بدقة أكبر: بدلاً من وجود فئة Result تحتوي على علامات وكائنات متداخلة، يمكنك استخدام OneOf<T0, T1, T2> حيث يمثل كل نوع حالة من الحالات المحتملة. هذا يجعل الكود أكثر تصريحية ويقلل من استخدام تركيبات if-else.
التثبيت
يتم تثبيت المكتبة عبر مدير الحزم NuGet. قم بتنفيذ أحد الأوامر التالية حسب أداتك:
# Package Manager Console
Install-Package OneOf
# .NET CLI
dotnet add package OneOf
# PackageReference (يدويًا في ملف .csproj)
<PackageReference Include="OneOf" Version="3.0.271" />
بعد التثبيت، أضف using OneOf; في بداية ملف الكود الخاص بك.
بداية سريعة
لنأخذ مثالًا بسيطًا: دالة تقسم رقمًا على آخر. بدلاً من إلقاء استثناء عند القسمة على صفر، سنرجع OneOf<double, string> — إما النتيجة أو رسالة خطأ.
using OneOf;
public OneOf<double, string> SafeDivide(double a, double b)
{
if (b == 0)
return "خطأ: القسمة على صفر";
return a / b;
}
// الاستخدام
var result = SafeDivide(10, 2);
result.Switch(
value => Console.WriteLine($"النتيجة: {value}"),
error => Console.WriteLine($"خطأ: {error}")
);
// الإخراج: النتيجة: 5
لاحظ: نحن لا نستخدم معاملات out، ولا نتحقق من null، ولا نلتقط الاستثناءات. كل ما نحتاجه هو استدعاء Switch أو Match وتوفير معالجات لكل احتمال محتمل.
الطرق والفئات الأساسية
توفر المكتبة عدة آليات رئيسية للعمل مع الاتحادات المميزة. دعنا نستعرض كل منها بالتفصيل.
1. OneOf<T0, T1, ...>
التوقيع: public class OneOf<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> : IOneOf
الوظيفة: الفئة الأساسية التي تمثل قيمة يمكن أن تكون من أحد الأنواع المحددة. تدعم حتى 9 أنواع. تحويل ضمني من أي من الأنواع المحددة إلى OneOf.
OneOf<int, string, bool> value = 42; // تحويل ضمني
value = "مرحبًا";
value = true;
// إنشاء صريح
var explicitValue = new OneOf<int, string>(100);
2. Switch
التوقيع: public void Switch(Action<T0> f0, Action<T1> f1, ...)
الوظيفة: تنفذ أحد الإجراءات المُمررة بناءً على القيمة المخزنة في OneOf. لا تُرجع أي قيمة.