post

#22 مكتبات الدوال Namespace – البرمجة بواسطة #C

رمز فتح مرحلة هذا الدرس في تطبيق طورني : VVG

تَعلُمُ البرمجةِ للمبتدئينَ كلياً بواسطةِ #C – التعامل مع المكتبات Namespace

تحدثنا في الدروس الماضية كيف أن Microsoft قامت بكتابة العديد من الدوال التي من هدفها أن تقوم بتسهيل عملنا على المشاريع. كيف قامت Microsoft بتنظيم و تصنيف هذه الدوال ، و ما هي الـ Assemblies ، و ما هي دلالة كلمة using ؟ هذا ما سوف نتعرف عليه في هذا الدرس ان شاء الله .

ما هي ال Assembly Code Files؟

كما تحدثنا في المقدمة فإن Microsoft قامت ببناء و كتابة آلاف من الدوال التي من هدفها أن تساعدنا في مشروعنا ، فكما لاحظنا و كثيراً استخدمنا دالة Consloe.WriteLine . WriteLine هي دالة لكتابة شيء على الشاشة ، هذه الدالة تمت كتابتها بواسطة Microsoft.

الشيء الذي نود توضيحه هنا هو أنه في كل مرة نقوم بإنشاء مشروع جديد يقوم المحرر باستدعاء الدوال التي تهمنا في هذا المشروع ، فمثلا عندما نقوم بعمل مشروع Console نجد أنه يستخدم بعضا من الـ References الموجودة على اليمين ،حيث نجد مثلا System , System.Core , System.Data ,System.Net.Http و غيرها .. ، هو فعليا يقوم باستدعاء هذه المكتبات ، و هذه المكتبات يمكن أن نبسطها على أنها ملفات Code Files تسمى Assemblies.

هذه الـ Assemblies قامت Microsoft بتقسيمها لأقسام كثيرة ، لأنه تخيل أن تقوم باستدعاء كافة المكتبات التي تكلمنا عنها – والتي تعتبر بمئات الآلاف من الـ Functions – ، فليس من المنطق أن تقوم باستدعاء كل هذه المكتبات ، لأنه أولا سينتج بطؤ شديد في التطبيق ، بالإضافة إلى أن كل الدوال ستخزن في الـ Memory الخاصة بالجهاز، و بالتالي لن يستطيع التعامل مع أي شيء آخر.

إذاً Microsoft قامت بتقسيم هذه الملفات إلى أقسام معينة ، و الجميل في الموضوع أنه كل مرة نقوم بكتابة Method داخل الـ Application الخاص بنا فإنه يمكننا إعادة تحويلها إلى Assembly ، حيث أننا إن شاء الله سنتعلم في الدرس القادم كيف يمكننا تحويل الـ Method التي قمنا بكتابتها إلى ملفات dll لكي نستخدمها في مشاريع أخرى مستقبلية .

ما هي دلالة كلمة Using؟

إذاً أنا قمت بفتح مشروع جديد Console و أسميته AssembliesAndNamespaces ، و بإمكانكم إيقاف الفيديو و الذهاب لعمل مشروع جديد ، قمت بكتابة سطرين فقط ، Console.WriteLine و Console.ReadLine . و لاحظو أن هذا النوع من المشاريع “الـ Console” يستدعي كما تكلمنا قبل قليل مجموعة من الـ References يمكن أن نجدها هنا في القائمة الموجودة على اليمين .

و من أهم الـ References المستخدمة في هذا المشروع هو الـ System ، و أحيانا من ضمن هذه الـ Libraries يتواجد أسماء Methods تتشابه مع أسماء Methods موجودة في كلاسات أخرى ، و لكي نقوم بحل هذه المشكلة يجب علينا أن نقوم باستدعاء الـ namespace الأصل الخاص بهذه الـ Method .

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

ذات الأمر في الكود الخاص بنا هنا ، فعندما نقوم باستخدام الـ namespace الكامل الخاص بالـ Method ، ثم كتابة الـ Method نكون قد قمنا بالحد من التضاربات الموجودة. فعندما ننظر هنا إلى الكود ، سنجد أن دالة Console موجودة في الـ namespace الذي اسمه System . و عند تعديل الكود ليصبح :

System.Console.WriteLine(“…”);

سأكون استدعيت الـ namespace الخاص بـ Console ، و استخدمتها مباشرةً ، نلاحظ أن الكلمة System أصبح لونها رمادياً ، و هذا يعني أنه يمكن الاستغناء عن الكلمة ، و لا يشترط أن أقوم بكتابتها. لأننها قمنا في الأعلى بكتابة :

using System;

و بذلك نكون قد أخبرنا التطبيق أنه “أي Method تابعة للـ namespace المسمى System ، قم باستخدامها مباشرة ، دون الحاجة لكتابة الـ namespace الخاص بها في كل مرة”.
فمثلا لو حذفت الـ 5 اسطر الأولى الموجودة في الأعلى ، سنجد مباشرة أن السطر رقم 9 :

System.Conole.WriteLine(“…”);

قد تحولت الكلمة System من اللون الرمادي إلى اللون الأبيض ، بمعنى أنه يجب استخدامها الآن
كما سنلاحظ ظهور خطأ في السطر العاشر . Console.ReadLine();

و قمنا بعمل Run للـ Application سنجد أن البرنامج تم تنفيذه بشكل صحيح دون مشاكل .

إذا للحد من الحاجة لكتابة الـ namespace في كل مرة نقوم باستخدام الكلمة using و هنا نكتب using System ، و عند كتابتها من جديد ستعود الكلمة System في السطر رقم 9 و 10 إلى اللون الرمادي ، بمعنى أنه ليس من الضروري كتابتها .

الكتابة على ملف File :

لنأخذ الآن مثالاً جديداً على كيفية استخدام Library خارج نطاق الشيء الذي نعمل فيه ، فمثلا في حالة الـ Console الشيء الذي نحتاجه هو الـ System ، و لكن ماذا لو أردنا كتابة text معين في ملف .
هنا يجب أن نستدعي Library الخاصة بعملية الكتابة على الملفات ، سنذهب إلى المتصفح للحصول على مثال موجود مسبقاً لنكتب في Google ” How to write to a text file C# ” سنلاحظ الكثير من النتائج التي ستظهر لدينا ، من بينها مجموعة الصفحات الخاصة بـ Microsoft ، و سنجد في هذه الصفحة 3 طرق للكتابة على file ، لنأخذ المثال الثاني هنا .

        // Example #2: Write one string to a text file.
        string text = "A class is the most powerful data type in C#. Like a structure, " +
                       "a class defines the data and behavior of the data type. ";
        // WriteAllText creates a file, writes the specified string to the file,
        // and then closes the file.    You do NOT need to call Flush() or Close().
        System.IO.File.WriteAllText(@"C:\Users\Public\TestFolder\WriteText.txt", text);


نلاحظ في السطر رقم 14 أنه يقوم باستخدام namespace اسمه System.IO لكي يستدعي الـ File و الدالة التي تقوم بكتابة النص على الـ File .
سنأخذ القسم System.IO و نقوم بوضعه في الأعلى إلى جوار الكلمة using ليصبح

Using System.IO;

ثم قمنا بحذف القسم من الدالة في الأسفل ، سنلاحظ عدم ظهور أي مشكلة ، و بالتالي يمكننا التعامل مع الدالة بدون مشاكل ، سأقوم بتغيير الـ path للـ File لنرى الناتج الذي سيظهر على الملف ، إذا عندما أقوم بعمل تشغيل للبرنامج ، و أذهب إلى المسار الذي وضعته هنا سأجد أنه قام بكتابة النص الموجود في المتغير text على الملف النصي .

تحويل صفحة إنترنت إلى نص وتخزينه

لنأخذ مثالاً آخر لكيفية عمل تنزلي لصفحة إنترنت و تحوليها إلى text و كتابته على الـ File ، لنذهب إلى المثال الآخر ، و الموجود أيضاً على صفحة Microsoft (C) ، يمكنكم البحث عن “How to download HTML as string” ، سنجد مثالاً في الأسفل ، لنأخذه و نضعه في المحرر الخاص بنا ، سنجد مثالاً في الأسفل ، لنأخذه و نضعه في المحرر الخاص بنا :

public static void DownloadString (string address)
{
    WebClient client = new WebClient ();
    string reply = client.DownloadString (address);

    Console.WriteLine (reply);
}

نلاحظ بمجرد عمل لصق للمثال ، يظهر لدينا مشكلة ، و ذلك لأن النوع WebClient غير معرف لدينا ، حيث أن الـ Compiler لم يقم بالتعرف على هذه الكلمة . و إذا وضعت مؤشر الماوس على الكلمة ، ستجد أن الـ namespace غير موجود ، و نلاحظ ظهور مصباح ذو لون أصفر أسفل الكلمة ، و بالضغط عليه سيعطينا خيارات لإصلاح هذه المشكلة ، نلاحظ أنه قام بتقديم حلين ، إما أن تقوم بكتابة using System.Net; أو أن تقوم بكتابة الـ namespace كاملاً في هذا السطر.

لنتفادى المشكلة سنقوم بعمل إضافة using System.Net; في الأعلى ، و ذلك بالضغط على الاقتراح الذي قام البرنامج بتقديمه. و عندها ستصبح باللون الأخضر ، و ذلك دلالة على أنها أصبحت معرفة لدى الـ Compiler .

سنقوم الآن باستبدال كلمة Address بالرابط الذي نريد نسخه ، و سنقوم بكتابة الناتج على الـى File
و عندما نقوم بتشغيل التطبيق ، و نذهب إلى الملف سنلاحظ أنه قام بطباعة كامل الصفحة كـ HTML

إذاً تعرفنا في هذا الدرس كيف يمكننا استخدام كلمة using ، و كيف يمكننا استدعاء أي Method نريد استخدامها سواء بكتابة الاسم الكامل لها أو كتابتها في القسم الأول (استدعاء المكتبات أو الـ Assemblies التي نريد استخدامها ) في مشروعنا .

post

#20 النطاق Scope – البرمجة بواسطة #C

رمز فتح مرحلة هذا الدرس في تطبيق طورني : BVP

تَعلُمُ البرمجةِ للمبتدئينَ كلياً بواسطةِ #C –  النطاق Scope

لماذا عندما نقوم بتتعريف متغير جديد ، لان نستطيع استخدامه في كل التطبيق ؟ ما هو الـ scope ؟ و ما هو النطاق الخاص بالمتغير ؟ و متى ينتهي المتغير و يتم حذفه من الذاكرة ؟

في درس اليوم سوف نتكلم عن النطاقات Scopes و أهميتها ، و ذكرنا سابقاً أننا سنقوم بشرحها مستقبلاً بشكل مكثف ، لدينا الآن برنامج Visual Studio 2019 Community و هو مجاني كما ذكرنا سابقاً، بإمكاننا عمل مشروع جديد من خلال Create new project و نقوم باختيار الـ Console app ثم الضغط على next و في الصفحة التالية نقوم بكتابة اسم مشروع ، و ليكن UnderstandingSscope ، سيفتح لنا النافذة الرئيسية للكود

الشيء الذي نريد إيصاله أنه عندما نقوم بتعريف متغير جديد ، فإنه سيكون متاحاً في القطعة البرمجية الموجود فيها حصراً ، أو كل القطع البرمجية الموجودة داخلها . و قد تكلمنا سابقاً أن القطعة البرمجية هي القطعة المحصورة بين القوسين { } ، سنقوم الآن بعمل حلقة for loop

 for (int i=0 ; i<10 ; i++)
 {
      Console.WriteLine(i.ToString());
 }
 Console.ReadLine(); 

فهم النطاق

اذا قمنا بتنفيذ المشروع ، فسنرى أنه قام بطباعة الأعداد من 0 إلى 9 كما هو المعتاد ، لكن لنلاحظ التالي ، لو قمنا بأخذ الجملة Console.WriteLine(i.ToString()); و كتابتها خارج القطعة البرمجية الموجودة فيها ( أي خارج القطعة الخاصة بالحلقة for loop ) ، يصبح الكود بالشكل :

 for (int i=0 ; i<10 ; i++)
 {
      Console.WriteLine(i.ToString());
 }
 Console.WriteLine(i.ToString());
 Console.ReadLine(); 

فنلاحظ أنه مباشرة سيظهر لدينا خطأ في قائمة الأخطاء ، و يقول الخطأ ، “the name does not exist in current context” ، بما معناه أن المتغير لا يمكن التعرف عليه في هذه المنطقة لأن الـ i حصراً لتلك القطعة البرمجية لأنها داخل نطاق الحلقة التكرارية ، بالتالي فإنه فعلياً غير موجود في القطعة البرمجية الأخرى ، و لن يتم التعامل معه .
سنقوم بجعل الجملة الخاطئة جملة تعليق . و سنقوم بعمل متغير جديد باسم j في القطعة الأولى ، و التي تحتوي على الحلقة for loop و نقوم بإسناده داخل القطعة البرمجية التابعة للحلقة for loop ، ثم نقوم بكتابة الجملة لتقوم بطباعة المتغير j خارج الحلقة for loop ليصبح الكود كالتالي :

{
     string j =” “ ;
     for (int i=0 ; i<10 ; i++)
     {
          Console.WriteLine(i.ToString());
          j = i.ToString();
     }
     // Console.WriteLine(i.ToString());
     Console.WriteLine(“j = “ + j.ToString());
     Console.ReadLine();
}

ثم نقوم بتنفيذ البرنامج … نلاحظ أنه يخبرنا في النهاية أن j تحصل على القيمة 9 ، نلاحظ أنه قمنا بتعريف المتغير j في القطعة الخارجية .. إذا لن يحدث أي خلل سواء استعملته في القطعة الداخلية أو في نفس القطعة التي قمت بتعريفه داخلها .

النطاق على مستوى ال Class

سنقوم بتعريف property جديدة من النوع String
Private static string k =” “ ;
و في الداخل ستكون قيمة k الجديدة ستكون هي قيمة i ، و سنقوم في الخارج بطباعة قيمة k الجديدة كما قمنا بطباعة قيمة j سابقاً ، بتنفيذ البرنامج نلاحظ أنه يعطيني نفس النتيجة النهائية . الشيء الذي نريد توضيحه أنه بحال قمت بتعريف method على مستوى الكلاس ، مثلا :

static void HelperMethod()
{
    K = “10” ;
}

و قمنا باستدعاء الـ HelperMethod في الأعلى ، ثم قمت بتنفيذ المشروع ، نلاحظ أن القيمة النهائية هي 10 ، لأن المتغير k على مستوى الكلاس ، فيمكنني استخدامه في أي منطقة داخل الكلاس ، و أنا قمت باستخدامه داخل method لأقوم بالتعديل عليه ، أيضا في جملة التكرار for سأقوم بوضع جملة شرطية ، في حال كان قيمة i هي 9 قم بتعريف متغير ، string l =” “ ; ، ثم نقوم مباشرة بطباعة هذا المتغير خارج اقواس الحلقة for loop ، مباشرة سيعطيني أن هناك خطأ … فهذا المتغير تم تعريفه في قطعة برمجية داخلية ، فهذا المتغير عندما يصل إلى نهاية القوس سينتهي و يختفي من الذاكرة ويكون خارج النطاق فلا يمكن استخدامه خارج هذه الاقواس . اذاً هناك نطاق لكل متغير ، ولا يمكن استخدامه خارج هذا النطاق ، و هذا الكلام ليس محصوراً فقط للمتغيرات ، فعندما نقوم باستنساخ مجسم من كلاس ، ينطبق عليه كل ما قمنا بتطبيقه في هذا الدرس ، هذا كان بشكل سريع ملخص لمفهوم النطاقات scopes .
نراكم ان شاء الله في درس قادم قريباً . السلام عليكم .

الأسطر البرمجية التي قمنا بتنفيذها في هذا الدرس

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace UnderstandingScope
{
    class Program
    {
        private static string k = "";
        static void Main(string[] args)
        {
            string j = "";
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine(i.ToString());
                j = i.ToString();
                k = i.ToString();

                if (i == 9)
                {
                    string l = "";
                }
                //Console.WriteLine(l);
            }
            //Console.WriteLine(i.ToString());
            Console.WriteLine("j = " + j.ToString());
            HelperMethod();
            Console.WriteLine("k = " + k.ToString());
            Console.ReadLine();
        }

        static void HelperMethod()
        {
            k = "10";
        }
    }
}