في جملة واحدة
إنها القوة الكاملة للغة البرمجة C#، ومترجم Roslyn، وبيئة تشغيل .NET، يتم نقلها بالكامل إلى متصفحك باستخدام WebAssembly — مما يتيح لك كتابة، تنفيذ، وتجميع الكود (compile) إلى ملف DLL حقيقي بدون الحاجة لتثبيت IDE حجمه عدة جيجابايت.
المشكلة التي يحلها
تاريخياً، كان تطوير C# هو التعريف الحقيقي للـ "heavy metal" (البرمجة الثقيلة). ظهرت في أوائل الألفينات كرد أنيق من مايكروسوفت على Java، وكانت C# مقيدة بشدة بنظام Windows. لو أردت كتابة سكريبت C# سريع أو اختبار كيف سيتصرف استعلام LINQ معين، لم يكن بإمكانك مجرد فتح الـ terminal. كان عليك تشغيل Visual Studio (ووقتها يمكنك أخذ استراحة قهوة بينما يحمل الـ splash screen)، ثم تنشئ مشروع جديد، وتسميه باسم ستندم عليه لاحقاً مثل ConsoleApp42، وتنتظر حتى تعمل حزم NuGet (restore)، ثم تكتب الخمسة أسطر الخاصة بك، وتشغلها، وفي النهاية تحذف المجلد.
مايكروسوفت أحدثت ثورة في هذا الأمر عندما جعلت .NET مفتوح المصدر (open-source) ومتعدد المنصات (cross-platform)، وقدمت الـ .NET CLI. لكن حتى مع ذلك، كنت لا تزال بحاجة لتنزيل وتثبيت SDK ضخم لمجرد عمل compile لبرنامج "Hello, World" بسيط.
كمطورين، نحن نعشق الـ instant feedback loops (الحصول على نتيجة فورية). نريد بناء نماذج أولية (prototype) للخوارزميات، والتحقق من الـ syntax، وإعادة إنتاج الأخطاء (reproduce bugs) بدون أي احتكاك أو تعطيل. نحن نحتاج إلى sandbox. لكن بالنسبة للغة typed و compiled مثل C#، كان إنشاء sandbox حقيقي على الويب يعني تقليدياً إرسال الكود إلى خادم خلفي (backend)، وعمل compile له هناك، ثم تشغيله داخل حاوية Docker، وإرسال الـ text output (النص الناتج) مرة أخرى إلى المتصفح. هذا الأسلوب بطيء، وتكلفة استضافته عالية، ويحتاج إلى اتصال دائم بالإنترنت.
الـ C# playground يحل هذه المشكلة عن طريق التخلص من السيرفر تماماً. حيث يجلب المترجم (compiler) وبيئة التشغيل (runtime) مباشرة إلى العميل (client)، مما يحول متصفحك إلى بيئة تطوير سريعة جداً ومؤقتة (ephemeral).
كيف يعمل من تحت الغطاء
تشغيل C# بشكل native في متصفح الويب يبدو وكأنه سحر أسود، ولكنه في الحقيقة مزيج أنيق بين إنجازين هندسيين ضخمين: WebAssembly ومترجم Roslyn Compiler.
بيئة تشغيل WebAssembly
تقنية WebAssembly (أو Wasm) هي تنسيق تعليمات ثنائي (binary instruction format) صُمم ليكون هدف تجميع (compilation target) محمول للويب. وهو يسمح للغات مثل C و C++ و Rust بالعمل في المتصفح بسرعات تقارب الـ native (السرعة الأصلية).
لكي تجعل مايكروسوفت C# تعمل في المتصفح، لم تقم بإعادة كتابة C# باستخدام JavaScript. بدلاً من ذلك، أخذوا بيئة تشغيل .NET (تاريخياً كانت Mono runtime، والآن تم توحيدها تحت .NET Wasm) وقاموا بعمل compile لنواتها المكتوبة بـ C/C++ إلى WebAssembly. عندما تفتح C# playground، يقوم متصفحك بتنزيل dotnet.wasm. هذه عبارة عن .NET Virtual Machine تعمل بكامل طاقتها وتعمل مباشرة داخل محرك V8 (أو SpiderMonkey، أو JavaScriptCore) في متصفحك.
مترجم Roslyn: كخدمة (Compiler as a Service)
قبل أن تتمكن بيئة تشغيل .NET من تنفيذ الكود الخاص بك، يجب تحويله (compiled) من لغة C# التي يقرأها البشر إلى لغة مايكروسوفت الوسيطة (Microsoft Intermediate Language والتي تعرف اختصاراً بـ MSIL أو IL فقط).
هنا يتدخل Roslyn. على عكس المترجمات القديمة التي كانت تتصرف كصناديق سوداء (تُدخل الـ source code، فيخرج لك ملف تنفيذي executable)، تم بناء Roslyn من الصفر باستخدام C# مع مجموعة غنية من الـ APIs. إنه "Compiler as a Service". ولأن Roslyn مكتوب بلغة C#، ولدينا بيئة تشغيل .NET تعمل في المتصفح عبر Wasm، يمكننا بالفعل تشغيل مترجم Roslyn داخل المتصفح.
دورة التنفيذ (The Execution Pipeline)
عندما تكتب الكود في الـ playground وتضغط على Run، هذا ما يحدث بالكامل داخل ذاكرة جهازك:
- التحليل (Parsing): يقوم مترجم Roslyn الموجود في المتصفح بتحليل النص الخام (parsing) وتحويله إلى Syntax Tree (شجرة بناء الجملة).
- التجميع (Compilation): يقوم Roslyn بعمل compile لـ Syntax Tree وتحويلها إلى in-memory assembly (ملف تجميع في الذاكرة بصيغة IL bytecode).
- التنفيذ (Execution): تقوم بيئة تشغيل .NET Wasm في المتصفح بتحميل هذا الـ assembly من الذاكرة وتنفذ تعليمات الـ IL. يتم اعتراض الـ Standard output (المخرجات القياسية مثل
Console.WriteLine) وتوجيهها إلى شاشتك.
تصدير ملف الـ DLL
لأن Roslyn يقوم بعملية compile حقيقية وقياسية، فإن الـ assembly الناتج في الذاكرة متطابق وظيفياً مع ملفات الـ .dll الموجودة على سطح مكتبك. يستطيع الـ playground ببساطة أخذ مصفوفة البايتات (byte array) تلك من الذاكرة وبدء تحميلها عبر المتصفح. أنت لا تحصل على DLL "وهمي" (mock)؛ بل تحصل على مكتبة .NET قياسية تم تجميعها (compiled) بواسطة المحرك الرسمي، وجاهزة ليتم وضعها في سيرفر، أو لعبة Unity، أو تطبيق سطح مكتب.
قصص من أرض الواقع
جدال "هل سيعمل Compile؟"
مطوران كانا منغمسين في مراجعة Pull Request. أصر أحدهما على أن استخدام تركيبة معينة من pattern matching الخاص بـ C# 12 و switch expressions سيؤدي إلى compiler error بسبب وجود unreachable code؛ بينما أقسم الآخر أنه syntax صحيح. لم يرغب أي منهما في عمل context-switch، و stash لتعديلات git المحلية، وإنشاء branch اختبار جديد. بدلاً من ذلك، قاما بنسخ الكود ولصقه في C# playground داخل المتصفح. في غضون ثلاث ثوانٍ، تم عمل compile للكود، وأخرج النتيجة المتوقعة، وحسم الرهان في لمح البصر.
الدرس المستفاد: أسرع طريقة لإنهاء جدال حول الـ semantics الخاصة باللغة هي الـ instant feedback loop (دورة الملاحظات الفورية) الخالية من أي احتكاك.
باني الـ DLL السريع (The quick-and-dirty DLL builder)
مستشار كان يعمل على لابتوب عميل مقيد (locked-down) ولم يكن لديه صلاحيات Administrator لتثبيت الـ .NET SDK. كان بحاجة ماسة لكتابة utility function صغيرة لتحليل صيغ سجلات (logs) خاصة، والتي كان تطبيقهم الرئيسي (الذي يدعم إضافات الـ DLL عن طريق السحب والإفلات) بحاجة لاستخدامها. بدلاً من انتظار تذكرة دعم الـ IT لمدة ثلاثة أيام لتثبيت Visual Studio، فتح المستشار C# playground، وكتب لوجيك التحليل (parsing logic)، وصدر ملف الـ DLL المعمول له compile، وأسقطه مباشرة في مجلد الإضافات (plugins) الخاص بالتطبيق. الدرس المستفاد: عندما يحتوي المتصفح على مترجم حقيقي، فإنه يصبح build server فعال ومثالي يتجاوز قيود الجهاز المحلي.
مقابلة الـ Sandbox
كان أحد الـ tech leads يجري مقابلة تقنية عن بُعد. بدلاً من إجبار المرشح على مشاركة شاشته مع إعدادات IDE ثقيلة أو التعامل مع الـ latency الخاص بالـ remote desktop، قاما بتسجيل الدخول إلى جلسة C# playground مشتركة. تمكن المرشح من كتابة استعلامات LINQ معقدة واختبار هياكل بيانات Object-oriented مع feedback في الوقت الفعلي (real-time)، مما أثبت مهاراته بدون ضغط ضبط إعدادات البيئة (environment configuration). الدرس المستفاد: وجود بيئة sandbox نقية ومعزولة يفصل مهارة المطور البرمجية الخام عن مهاراته في إدارة النظام.
أخطاء شائعة وفخاخ
- افتراض أن لديك نظام ملفات (file system) حقيقي: يمكنك استخدام كلاسات
System.IO، لكنك تتفاعل مع نظام ملفات افتراضي ومؤقت توفره بيئة WebAssembly. إذا كتبت ملفاً فيC:\temp\log.txt، فهو يعيش في ذاكرة المتصفح وسيختفي بمجرد عمل refresh للصفحة. - استدعاء مكتبات الـ OS الأصلية (native libraries): محاولة استخدام (P/Invoke) لاستدعاء Windows APIs أصلية مثل
[DllImport("user32.dll")]ستفشل فشلاً ذريعاً ومضحكاً. نظام التشغيل الخاص بك الآن هو متصفح الويب؛ لا وجود لمكتبات سطح المكتب الأصلية هنا. - التعامل معه كأنه High-performance cluster: تقنية WebAssembly سريعة، لكنها معزولة بشدة (sandboxed) من قبل المتصفح وغالباً ما تكون مقيدة في الذاكرة وقدرات الـ threading. الـ playground عبقري لاختبار الـ logic، ولكنه مريع لتشغيل
Parallel.ForEachمتوازي على dataset بحجم 2 جيجابايت. - فخ الـ
async void: عند كتابة سكريبتات سريعة، من السهل أن تنسى أن الـMainتحتاج أن ترجعasync Taskإذا كنت تستخدمawaitفي العمليات. استخدامasync voidفي الـ sandbox يمكن أن يؤدي إلى قيام الـ runtime بإغلاق الـ execution context قبل أن تنتهي مهامك غير المتزامنة (asynchronous tasks) فعلياً، مما يؤدي إلى فشل صامت (silent failures). - نسيان الـ assembly references: إذا كنت تحاول تصدير ملف DLL، تذكر أن الكود الخاص بك يتم عمل compile له باستخدام الـ base class libraries المتوفرة في الـ sandbox. إذا اعتمدت على حزم NuGet خارجية (third-party) غير محملة في سياق Roslyn الخاص بالـ playground، فلن يتم عمل compile للكود الخاص بك.
لماذا يجب أن يكون على رادارك
يجب أن تلجأ إلى C# playground كلما كان العبء الذهني أو الفعلي لفتح IDE كامل أكبر من المهمة التي بين يديك. إنها الأداة المثالية لاختبار الميزات الجديدة في اللغة (مثل استكشاف primary constructors أو collection expressions في إصدارات C# الحديثة) دون الحاجة لترقية سلسلة أدواتك المحلية (local toolchain).
هو أيضاً أصل لا يقدر بثمن لمشاركة أمثلة قابلة لإعادة الإنتاج (reproducible examples). إذا وجدت bug في مكتبة مفتوحة المصدر أو أردت طرح سؤال على StackOverflow، فإن توفير رابط لـ playground حيث يمكن إعادة إنتاج السلوك نفسه على الفور هو أمر مفيد أكثر بمليون مرة من لصق جدار من النص وتمني أن يقوم الشخص الآخر بضبط بيئته بشكل صحيح. وأخيراً، فإن القدرة على تصدير ملف .dll حقيقي بسهولة يجعله أداة compilation قوية لا تحتاج لأي تثبيت، لإنشاء إضافات (plugins) خفيفة ومكتبات مساعدة (helper libraries) على الطاير (on the fly).
تعمق أكثر
- مفاهيم WebAssembly (MDN Web Docs) - البنية الأساسية لكيفية تنفيذ Wasm للكود الثنائي (binary code) في المتصفح.
- مستودع Roslyn Compiler على GitHub - الموطن مفتوح المصدر لمترجم C#، حيث يمكنك استكشاف كيف يتم تطبيق مفهوم "Compiler as a Service".
- تشغيل .NET من WebAssembly (Microsoft Learn) - التوثيق الرسمي لكيفية عمل بيئة تشغيل .NET داخل الـ Wasm sandbox.
- Standard ECMA-335: البنية التحتية المشتركة للغات (CLI) - المواصفات التقنية العميقة للـ MSIL/IL bytecode الذي يقوم الـ playground بتوليده وتصديره.