إنشاء مجلد إذا لم يكن موجودًا في C#: كيف لا تبطئ الكود

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

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

ابدأ الدورة

لماذا أصبح سؤال "إنشاء مجلد إذا لم يكن موجودًا" ميمًا في C#

\n\n

إذا كنت قد كتبت أي كود يقوم بحفظ الملفات، أو معالجة التقارير، أو تخزين البيانات مؤقتًا، فمن المحتمل أنك واجهت موقفًا: "ماذا لو كان المجلد غير موجود؟". قد يبدو الأمر بسيطًا؟ تتحقق - ثم تنشئ. لكن في الممارسة العملية، تتحول هذه المهمة إلى مغامرة حقيقية مليئة بالأخطاء والبطء والاستثناءات.

\n\n

على Stack Overflow، حصد سؤال "If a folder does not exist, create it" مئات الآلاف من المشاهدات. وهذا ليس من قبيل الصدفة. حتى المطورون ذوو الخبرة يكتبون أحيانًا كودًا يبدو أنه يعمل، لكنه يقتل الأداء أو يفشل في السيناريوهات متعددة الخيوط.

\n\n

في هذه المقالة، سنناقش كيفية إنشاء مجلد بشكل صحيح في C# إذا لم يكن موجودًا دون الوقوع في الأخطاء. ستتعلم لماذا Directory.CreateDirectory ليس مجرد "إنشاء"، بل أداة قوية للتحسين، وكيفية كتابة كود لا يبطئ حتى على الأقراص البطيئة.

\n\n

النهج الأكثر شيوعًا (والخاطئ)

\n\n

عندما يواجه المبتدئ هذه المهمة لأول مرة، عادةً ما يكتب شيئًا مثل:

\n\n
if (!Directory.Exists(path))\n{\n    Directory.CreateDirectory(path);\n}\n
\n\n

للوهلة الأولى - يبدو منطقيًا. تحقق من عدم وجود المجلد، ثم أنشئه. لكن دعنا نرى ما يحدث تحت الغطاء.

\n\n

المشكلة رقم 1: استدعاء مزدوج لنظام الملفات

\n

Directory.Exists يقوم باستعلام لنظام الملفات. Directory.CreateDirectory يقوم باستعلام آخر (أو عدة استعلامات). في النهاية، نصل إلى القرص مرتين. على SSD هذا ليس حرجًا، لكن على المجلدات الشبكية أو الأقراص الصلبة البطيئة (HDD)، كل عملية إضافية تعني فقدان ميلي ثانية. وماذا لو كان هناك مئات من هذه التحققات؟

\n\n

المشكلة رقم 2: حالة السباق (race condition)

\n

تخيل أن خيطين (threads) ينفذان هذا الكود في نفس الوقت. كلاهما يتحقق - المجلد غير موجود. كلاهما يحاول الإنشاء. أحدهما ينشئ بنجاح، والثاني يفشل مع IOException ("المجلد موجود بالفعل"). أو ما هو أسوأ، كلاهما ينشئ، لكن أحدهما يعيد كتابة صلاحيات الوصول التي حددها الآخر.

\n\n

المشكلة رقم 3: شعور زائف بالأمان

\n

يعتقد الكثيرون: "لقد تحققت - إذن كل شيء على ما يرام". لكن بين التحقق والإنشاء قد تمر ميكروثانية، يمكن خلالها لعملية أخرى إنشاء هذا المجلد. أو قد يحجب برنامج مكافحة الفيروسات الإنشاء. أو قد تنفد المساحة على القرص.

\n\n

النهج الصحيح: Directory.CreateDirectory - صديقك

\n\n

والآن المفاجأة: توثيق Microsoft يقول مباشرة أن Directory.CreateDirectory يتحقق بنفسه من وجود المجلد. إذا كان موجودًا - لا يفعل شيئًا (يعيد كائن DirectoryInfo للمجلد الموجود). إذا لم يكن موجودًا - ينشئه.

\n\n

أي أن الكتلة الكاملة مع if غير ضرورية! يكفي فقط:

\n\n
Directory.CreateDirectory(path);\n
\n\n

هذا ليس فقط أقصر، بل أفضل في الأداء و أكثر أمانًا في البيئات متعددة الخيوط. الطريقة ذرية من وجهة نظر نظام الملفات: إما أن تنشئ المجلد، أو تتأكد من وجوده بالفعل، وتعيد التحكم.

\n\n

لماذا هذا أسرع؟

\n

لأنه داخل CreateDirectory يتم استخدام دالة WinAPI CreateDirectory، والتي في حالة وجود المجلد تعيد ببساطة ERROR_ALREADY_EXISTS. لا اجتياز إضافي للدليل. استدعاء نظام واحد بدلاً من اثنين.

\n\n

غوص عميق: كيف يعمل Directory.CreateDirectory

\n\n

دعنا نلقي نظرة على الكود الحقيقي. الطريقة لا تنشئ المجلد النهائي فقط، بل جميع الدلائل الأصلية (parent directories) في المسار. هذا سبب آخر لعدم كتابة منطقك الخاص.

\n\n
string path = @"C:\\Projects\\Reports\\2025\\January\\Data";\nDirectory.CreateDirectory(path);\n// إذا كان C:\\Projects غير موجود - سينشئه.\n// إذا كان Reports غير موجود - سينشئه.\n// وهكذا، حتى Data.\n
\n\n

بدون هذا، كان عليك تقسيم المسار بشكل متكرر وإنشاء

المدونات

توصيات الكتب