علامتا الاستفهام في C#: ما هما وكيفية استخدامهما

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

علامتا الاستفهام في C#: ليست خطأ، بل أداة قوية

\n\n

تخيل: أنت تكتب كودًا بلغة C#، وفجأة ترى تركيب ??. أول فكرة تتبادر إلى ذهنك — خطأ مطبعي؟ علامة زائدة؟ في الحقيقة، هذا واحد من أكثر عوامل اللغة أناقة وفائدة — عامل دمج القيم الخالية (null-coalescing operator). إذا كنت قد واجهت يومًا NullReferenceException ولعنت كل شيء — فهذا العامل سيكون طوق نجاة لك.

\n\n

في هذه المقالة، سنشرح ما تعنيه علامتا الاستفهام في C#، وكيفية استخدامهما بشكل صحيح، وما الفرق بينهما وبين العامل الثلاثي، وسنعرض أمثلة حقيقية من الممارسة. هيا بنا!

\n\n

ما هو العامل ?? في C#؟

\n\n

العامل ?? (علامتا استفهام) هو عامل ثنائي يُرجع المعامل الأيسر إذا لم يكن يساوي null؛ وإلا فإنه يُرجع المعامل الأيمن. ببساطة: "إذا كان اليسار ليس null — خذ اليسار، وإلا خذ اليمين".

\n\n

التركيب بسيط للغاية:

\n\n
var result = left ?? right;
\n\n

حيث:

\n
    \n
  • left — قيمة قد تكون null؛
  • \n
  • right — قيمة افتراضية (لا يمكن أن تكون null إذا كان النوع الأيمن nullable).
  • \n
\n\n

المثال الأول: النجاة من null

\n\n

لنفترض أن لديك متغير string? name (سلسلة nullable). تريد عرض اسم المستخدم، وإذا لم يكن موجودًا — "ضيف":

\n\n
string? name = GetUserName(); // قد يُرجع null\nstring displayName = name ?? "ضيف";\nConsole.WriteLine(displayName);
\n\n

بدون العامل ??، كان عليك كتابة:

\n\n
string displayName = (name != null) ? name : "ضيف";
\n\n

أوافقك الرأي، الخيار الأول يُقرأ كجملة عادية: "الاسم أو ضيف". جميل، أليس كذلك؟

\n\n

العامل ??=: الجيل الجديد من دمج القيم الخالية

\n\n

بدءًا من C# 8.0، ظهر العامل ??= — وهو صيغة مختصرة للإسناد مع دمج القيم الخالية. يُسند قيمة المعامل الأيمن إلى المعامل الأيسر، فقط إذا كان المعامل الأيسر يساوي null.

\n\n

التركيب:

\n\n
left ??= right;
\n\n

هذا يعادل:

\n\n
if (left == null) left = right;
\n\n

مثال مع ??=

\n\n
List<int>? numbers = null;\nnumbers ??= new List<int>(); // numbers الآن = new List<int>()\nnumbers.Add(42);\nConsole.WriteLine(numbers.Count); // 1
\n\n

لاحظ: إذا كان numbers قد تمت تهيئته بالفعل (ليس null)، فلن يحدث الإسناد. هذا مثالي للتهيئة البطيئة (lazy initialization).

\n\n

مقارنة مع العامل الثلاثي (? :)

\n\n

كثير من المبتدئين يخلطون بين ?? والعامل الثلاثي ? :. دعنا نوضح الأمر مرة واحدة وإلى الأبد:

\n\n
    \n
  • العامل الثلاثي — هو صيغة مختصرة لـ if-else. يتحقق من أي شرط منطقي: شرط ? قيمة_إذا_صحيح : قيمة_إذا_خاطئ.
  • \n
  • العامل ?? — يتحقق فقط من null. هذه حالة خاصة، مصممة لمهمة واحدة.
  • \n
\n\n

مثال على العامل الثلاثي:

\n\n
int age = 18;\nstring status = (age >= 18) ? "بالغ" : "قاصر";
\n\np>وإليك ما سيحدث إذا حاولت استبدال ?? بالعامل الثلاثي:

\n\n
string? name = null;\nstring displayName = name != null ? name : "ضيف"; // يعمل، لكنه أطول\nstring displayName2 = name ?? "ضيف"; // أقصر وأوضح
\n\n

الخلاصة: استخدم ?? عندما تحتاج ببساطة إلى استبدال قيمة افتراضية بدلاً من null. لجميع الشروط الأخرى — استخدم العامل الثلاثي.

\n\n

سلسلة العوامل ??

\n\n

يمكنك ربط عدة عوامل ?? في سلسلة. هذا مفيد عندما يكون هناك عدة مصادر محتملة للقيمة:

\n\n
string? firstChoice = GetFromCache                

المدونات

توصيات الكتب