You are on page 1of 225

-0

-

‫الجزء األول‬

‫المستوى‪:‬‬
‫‪ ‬مبتدئ‪.‬‬
‫‪ ‬متوسط‪.‬‬

‫اعداد‪:‬المهندس حسام الدين الرز‬

‫‪-1-‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬

‫بسم اهلل الرمحن الرحيم‬

‫ُ ْ َ َ َ َ ْ َ َ َ ا َ َا ْ َ َ ا َ ْ َ‬
‫سبح انك َل ِع لم لن ا ِإَل م ا ع لمتن ا ِإنك أن ت‬
‫ُ‬ ‫ْ َ ُ ْ َ‬
‫كيم‬
‫ال ع ِليم الح ِ‬

‫‪-2-‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬

‫اهداء‪:‬‬
‫ا قدم هدا الكتاب معطرا بعطر يا سمين د مشقي ‪..‬‬

‫ي‬ ‫س‬ ‫ل‬ ‫لغ‬ ‫ي‬‫ب‬ ‫ح‬ ‫ل إل‬
‫ب‬ ‫ا‬
‫إ ي ة ا ة ور ا‪..‬‬‫ب‬

‫وادعوا الله لها و لأبتاء سعبي يا لخلاص الغاجل والفرج الف يرب ‪..‬‬

‫إلي امي البي ا عجر عن سكرها‪..‬‬

‫إلي والدي الدي حملبي مشولبة إلحتاة متكرا‪..‬‬

‫إلي ا خوتي وا خواتي ‪..‬‬

‫ق‬ ‫ش‬‫م‬ ‫ي‬‫س‬ ‫ل‬‫ا‬ ‫ق‬ ‫ب‬ ‫ي‬ ‫ه‬‫ل ق ت لغ لي عل قلب خ من‬
‫إ ي ا صد ا ي ا ا ن ي ي و ا ص م ا د ر د ي ف د ي ‪..‬‬
‫ل‬‫ا‬ ‫ص‬ ‫ك‬ ‫ل‬

‫إلي من تشا ط تري هموم إلحتاة و متا عنها روجبي الغالبة ‪..‬‬

‫جشام الدين الرر‬

‫‪-3-‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬

‫في حال وجود أي استفسار يرجى التواصل على اإليميل‪:‬‬ ‫‪Freesyria.syria123@gmail.com‬‬ ‫‪-4-‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .

‫الفهرس‬ ‫رقم الصفحة العنوان‬ ‫اهداء‬ ‫‪3‬‬ ‫الفهرس‬ ‫‪5‬‬ ‫مقدمة‬ ‫‪9‬‬ ‫الفصل األول‬ ‫‪13‬‬ ‫ما هو إطار عمل ‪.NET‬؟‬ ‫‪13‬‬ ‫ماذا يوجد ضمن إطار عمل ‪.NET‬؟‬ ‫‪14‬‬ ‫المكونات‬ ‫‪16‬‬ ‫الشيفرة البرمجية المدارة‬ ‫‪17‬‬ ‫مجمع النفايات‬ ‫‪17‬‬ ‫ماهي الخطوات الالزمة إلنشاء تطبيق ‪.NET‬‬ ‫‪23‬‬ ‫تطبيقات ‪Console‬‬ ‫‪24‬‬ ‫تطبيقات ‪Windows Forms‬‬ ‫‪28‬‬ ‫الخالصة‬ ‫‪32‬‬ ‫الفصل الثالث‬ ‫‪33‬‬ ‫التعليقات‬ ‫‪33‬‬ ‫البنية األساسية لتطبيق ‪ Console‬مكتوب بلغة ‪C#‬‬ ‫‪34‬‬ ‫المتغيرات (المتحوالت) والثوابت‬ ‫‪35‬‬ ‫التصريح عن المتغيرات‬ ‫‪35‬‬ ‫تسمية المتغيرات‬ ‫‪36‬‬ ‫قواعد التسمية‬ ‫‪37‬‬ ‫تطبيق حول التصريح عن المتغيرات والتعامل معها‬ ‫‪38‬‬ ‫القيم الحرفية‬ ‫‪40‬‬ ‫القيم الحرفية النصية‬ ‫‪41‬‬ ‫تطبيق حول استخدام القيم الحرفية النصية‬ ‫‪42‬‬ ‫التصريح عن المتغير واسناد قيمة له‬ ‫‪43‬‬ ‫‪-5-‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .NET‬؟‬ ‫‪18‬‬ ‫الربط‬ ‫‪18‬‬ ‫ما هي لغة ‪C#‬‬ ‫‪18‬‬ ‫ما نوع التطبيقات التي يمكن تطويرها باستخدام لغة ‪C#‬‬ ‫‪19‬‬ ‫برنامج ‪.NET‬‬ ‫‪19‬‬ ‫الخالصة‬ ‫‪21‬‬ ‫الفصل الثاني‬ ‫‪22‬‬ ‫بيئة التطوير المتكاملة ‪Visual Studio.NET‬؟‬ ‫‪14‬‬ ‫كيف يمكن كتابة التطبيقات باستخدام إطار عمل ‪.Visual Studio.

‫التعابير‬ ‫‪43‬‬ ‫العوامل الرياضية‬ ‫‪44‬‬ ‫تطبيق حول العوامل الرياضية‬ ‫‪45‬‬ ‫تطبيق أخر حول معالجة المتغيرات بالعوامل الرياضية‬ ‫‪47‬‬ ‫عوامل اإلسناد‬ ‫‪49‬‬ ‫أسبقية العوامل‬ ‫‪50‬‬ ‫فضاء األسماء‬ ‫‪51‬‬ ‫الخالصة‬ ‫‪56‬‬ ‫الفصل الرابع‬ ‫‪57‬‬ ‫المنطق البولياني‬ ‫‪57‬‬ ‫العوامل الخاصة بالبتات‬ ‫‪61‬‬ ‫تطبيق حول العوامل المنطقية والعوامل الخاصة بالبتات‬ ‫‪64‬‬ ‫عوامل االلحاق البوليانية‬ ‫‪66‬‬ ‫تطبيق حول استخدام العوامل المنطقية والعوامل الخاصة بالبتات‬ ‫‪66‬‬ ‫أسبقية العوامل‬ ‫‪68‬‬ ‫تعليمة ‪goto‬‬ ‫‪68‬‬ ‫التفرع‬ ‫‪70‬‬ ‫العامل ثالثي الحدود‬ ‫‪70‬‬ ‫تطبيق حول العامل ثالثي الحدود‬ ‫‪71‬‬ ‫تعليمة ‪if‬‬ ‫‪72‬‬ ‫تطبيق حول استخدام تعليمة ‪if‬‬ ‫‪74‬‬ ‫تفحص شروط إضافية باستخدام تعليمات ‪if‬‬ ‫‪75‬‬ ‫تعليمة ‪switch‬‬ ‫‪77‬‬ ‫تطبيق حول استخدام تعليمة ‪switch‬‬ ‫‪80‬‬ ‫تطبيق أخر حول استخدام تعليمة ‪switch‬‬ ‫‪82‬‬ ‫الحلقات‬ ‫‪83‬‬ ‫حلقات ‪DO‬‬ ‫‪84‬‬ ‫تطبيق الحساب البنكي باستخدام حلقة ‪do‬‬ ‫‪86‬‬ ‫حلقات ‪while‬‬ ‫‪88‬‬ ‫حلقات ‪for‬‬ ‫‪90‬‬ ‫تطبيق حول استخدام حلقة‪: FOR‬‬ ‫‪92‬‬ ‫مقاطعة الحلقات‬ ‫‪93‬‬ ‫الحلقات الالنهائية‬ ‫‪94‬‬ ‫الخالصة‬ ‫‪96‬‬ ‫الفصل الخامس‬ ‫‪97‬‬ ‫تحويل النوع‬ ‫‪97‬‬ ‫التحويالت المطلقة (الضمنية)‬ ‫‪98‬‬ ‫التحويالت الصريحة‬ ‫‪100‬‬ ‫‪-6-‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .

‫التحويالت الصريحة بواسطة أوامر التحويل‬ ‫‪103‬‬ ‫تطبيق حول تحويالت األنواع‬ ‫‪105‬‬ ‫أنواع المتحوالت المعقدة‬ ‫‪107‬‬ ‫التعدادات‬ ‫‪108‬‬ ‫تعريف التعدادات‬ ‫‪108‬‬ ‫تطبيق حول التعدادات‬ ‫‪111‬‬ ‫تطبيق أخر حول التعدادات‬ ‫‪114‬‬ ‫البنى‬ ‫‪115‬‬ ‫تعريف البنى‬ ‫‪116‬‬ ‫تطبيق حول استخدام البنى‬ ‫‪117‬‬ ‫تطبيق أخر حول البنى‬ ‫‪119‬‬ ‫المصفوفات‬ ‫‪120‬‬ ‫التصريح عن المصفوفات‬ ‫‪121‬‬ ‫تطبيق حول استخدام المصفوفات‬ ‫‪123‬‬ ‫حلقات ‪foreach‬‬ ‫‪125‬‬ ‫تطبيق أخر حول استخدام المصفوفات‬ ‫‪126‬‬ ‫المصفوفات متعددة األبعاد‬ ‫‪127‬‬ ‫تطبيق حول استخدام المصفوفات متعددة األبعاد‬ ‫‪130‬‬ ‫مصفوفات المصفوفات‬ ‫‪131‬‬ ‫خصائص ودوال المصفوفات‬ ‫‪133‬‬ ‫تطبيق حول استخدام خصائص ودوال المصفوفات‬ ‫‪134‬‬ ‫اللوائح‬ ‫‪138‬‬ ‫التصريح عن اللوائح‬ ‫‪138‬‬ ‫تطبيق حول استخدام اللوائح‬ ‫‪138‬‬ ‫خصائص ودوال اللوائح‬ ‫‪140‬‬ ‫تطبيق حول استخدام خصائص ودوال اللوائح‬ ‫‪140‬‬ ‫معالجة السالسل النصية‬ ‫‪142‬‬ ‫تطبيق حول معالجة النصوص‬ ‫‪147‬‬ ‫اإلكمال التلقائي للتعليمات في ‪Visual Studio‬‬ ‫‪148‬‬ ‫الخالصة‬ ‫‪151‬‬ ‫الفصل السادس‬ ‫‪152‬‬ ‫تعريف واستخدام التوابع‬ ‫‪153‬‬ ‫تطبيق حول تعريف واستخدام توابع أساسية‬ ‫‪156‬‬ ‫القيم المعادة‬ ‫‪158‬‬ ‫البارامترات‬ ‫‪158‬‬ ‫تطبيق حول تبادل البيانات مع التوابع‬ ‫‪160‬‬ ‫تطابقات البارامترات‬ ‫‪161‬‬ ‫مصفوفة البارامترات‬ ‫‪162‬‬ ‫‪-7-‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .

‫تطبيق آخر حول تبادل البيانات مع التوابع‬ ‫‪162‬‬ ‫بارامترات المرجع وبارامترات القيمة‬ ‫‪164‬‬ ‫بارامترات الخرج‬ ‫‪166‬‬ ‫مدى المتحول‬ ‫‪168‬‬ ‫تطبيق حول تعريف واستخدام تابع بسيط‬ ‫‪168‬‬ ‫مدى المتحوالت في بنى أخرى‬ ‫‪171‬‬ ‫البارامترات والقيم المعادة مقابل البيانات العامة‬ ‫‪174‬‬ ‫التابع )(‪Main‬‬ ‫‪175‬‬ ‫تطبيق حول بارامترات سطر االوامر‬ ‫‪176‬‬ ‫توابع البنية ‪Struct‬‬ ‫‪178‬‬ ‫التحميل الزائد للتوابع‬ ‫‪179‬‬ ‫المفوضات‬ ‫‪181‬‬ ‫المفوض الستدعاء تابع‬‫ّ‬ ‫تطبيق حول استخدام‬ ‫‪181‬‬ ‫االستدعاء التعاودي‬ ‫‪184‬‬ ‫الخالصة‬ ‫‪186‬‬ ‫الفصل السابع‬ ‫‪187‬‬ ‫األخطاء النحوية‬ ‫‪187‬‬ ‫األخطاء المنطقية‬ ‫‪188‬‬ ‫تنقيح األخطاء في ‪Visual Studio 2013‬‬ ‫‪189‬‬ ‫التنقيح في نمط عدم المقاطعة‬ ‫‪189‬‬ ‫إخراج معلومات التنقيح‬ ‫‪191‬‬ ‫تطبيق حول طباعة نص في إطار ‪Output‬‬ ‫‪192‬‬ ‫التنقيح في نمط المقاطعة‬ ‫‪200‬‬ ‫الدخول في نمط المقاطعة‬ ‫‪200‬‬ ‫نمط المقاطعة‬ ‫‪201‬‬ ‫طرق أخرى للدخول في نمط المقاطعة‬ ‫‪205‬‬ ‫مراقبة محتوى المتحوالت‬ ‫‪207‬‬ ‫الخطو خالل الشيفرة‬ ‫‪210‬‬ ‫األوامر الفورية‬ ‫‪211‬‬ ‫اإلطار ‪Call Stack‬‬ ‫‪212‬‬ ‫معالجة األخطاء‬ ‫‪213‬‬ ‫االعتراضات‬ ‫‪213‬‬ ‫التركيب ‪try.finally‬‬ ‫‪214‬‬ ‫تطبيق حول كتابة نص في نافذة الخرج‬ ‫‪216‬‬ ‫سرد وإعداد االعتراضات‬ ‫‪221‬‬ ‫مالحظات ح ول معالجة االعتراضات‬ ‫‪222‬‬ ‫الخالصة‬ ‫‪224‬‬ ‫‪-8-‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .catch...

NET‬دون‬ ‫االعتماد المباشر على نظام التشغيل ف الشيفرة المكتوبة بلغة ‪ C#‬ال تتخاطب مع نظام التشغيل مباشرة وإنما مع إطار عمل ‪.C#‬ال تق لق بشأن المكونات‬ ‫سوف يتم شرحها في الدروس الق ادمة‪.‬صدرت هذه اللغة‬ ‫في حزيران عام ‪ 0222‬فهي مازالت حديثة العهد‪ .NET‬وهذا واضح من خالل تصريحات شركة ‪ Microsoft‬والتي تشير إلى أن لغة ‪ C#‬هي اللغة االم لكتابة تطبيق ات‬ ‫تعتمد على منصة ‪.‬‬ ‫‪ -0‬لغة حديثة‪ :‬أن معالجة االست ثناء وأنواع البيانات الق ابلة للتوسع وكذلك أمن األوامر هي سمات تتصف بها اللغات‬ ‫الحديثة ‪ pointer‬مكون أساسي في لغتي ‪ C‬و‪ C++‬وهذا المكون من أكثر األجزاء التي تسبب االلتباس لدى‬ ‫المبرمجين‪ .‬وقد تم ألغاء العديد من التعقيدات والمشاكل التي يحدثها هذا المكون في ‪ .‬تسمى هذه المكتبة‬ ‫بإطار عمل ‪ ..‬إذا كنت ممن‬ ‫يدرسون ‪ C#‬أول مرة ف ال داعي لدراسة هذه الموضوعات‪.‬‬ ‫‪-9-‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ . ‫مقدمة‪:‬‬ ‫‪Introduction:‬‬ ‫تعتبر لغة السي شارب الموضوع الساخن الذي يطرحه المبرمجون اليوم أثناء حديثهم عن تطوير التطبيق ات وتعد هذه اللغة‬ ‫ثورة نوعية في األوساط البرمجية شبيه بتلك الثورة التي حدثت في التسعينات عندما صدرت لغة برمجة الجاف ا‪ .NET‬‬ ‫إن لغة برمجة ‪ C#‬هي لغة كائنية التوجه (‪ )Object-oriented programming -OOP‬تجمع بين القوة البرمجية للغة‬ ‫‪ C++‬وبين سهولة وبساطة البرمجة بلغة ‪ Visual Basic‬ولن أبالغ إذا ق لت أن هذه اللغة ق امت بجمع مزايا لغات البرمجة السابقة‬ ‫مثل ‪ Delphi‬و ‪ Java‬وابتعدت عن مساوئ هذه اللغات و أخطائها‪.‬‬ ‫ل قد صممت لغة ‪ C#‬من قبل شركة ‪ Microsoft‬لتعمل على منصة خاصة بها تسمى تلك المنصة بإطار عمل ‪ – .‬ومن أهداف لغة ‪:C#‬‬ ‫‪ -1‬لغة بسيطة‪ :‬جاءت ‪ C#‬لتقضي على التعقيدات والمشاكل الخاصة باللغات مثل ‪ Java‬و‪ C++‬فق امت بالغاء الماكرو‬ ‫والقوالب والتوارث المتعدد فهذه تسبب االلتباس لدى مطوري ‪ C++‬وكذلك ظهور المشاكل‪ .‬تم أنشاءها من قبل شركة ‪ Microsoft‬بواسطة فريق ‪ Microsoft‬بقيادة‬ ‫أندرس هيجلزبرج وهو مهندس متميز في ‪ Microsoft‬ق ام بإنتاج منتجات ولغات برمجة أخرى بما في ذلك "بورالند توربو ‪C++‬‬ ‫وبورالند دلفي" وركز المهند س في السي شارب على أخذ نق اط القوة التي تتصف فيها اللغات األخرى مع أضافة التحسينات لجعل‬ ‫هذه اللغة أفضل‪.‬‬ ‫تضع شركة ‪ Microsoft‬جملة من األهداف من أنشاء لغ ة برمجة‪ .NET‬‬ ‫لقد صممت شركة ‪ Microsoft‬مجموعة من العمليات واالجراءات ضمن مكتبة ضخمة جدا توفر هذه المكتبة على المبرمجين‬ ‫عناء كتابة الكثير من الشيفرات البرمجية التي يمكن أن توجد بصورة مجردة أو بشكل قياسي لالستخدام العام‪ .

‬‬ ‫إذا كانت لديك خبرة مسبقة بإحدى لغات البرمجة ولو كانت خبرة ضئيلة ولكنك تود تعلم كيفية البرمجة باستخدام‬ ‫‪‬‬ ‫إطار عمل ‪ .10 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .NET‬ف إطار عمل ‪ .‬‬ ‫‪ -5‬لغة ذات كلمات ق ليلة‪ :‬تستخدم لغة ‪ C#‬كلمات دليليه أو أساسية ق ليلة وهي األساس التي تبنى عليه إ جراءات اللغة‪.‬‬ ‫إن هذا الكتاب مثالي لنوعين من المبتدئين‪:‬‬ ‫إذا كنت مبتدئا في عالم البرمجة واخترت لغة ‪ C#‬لتبدأ معها مشوارك سيساعدك هذا الكتاب على تعلم مف اهيم‬ ‫‪‬‬ ‫برمجية قوية جدا ستعتبر ركيزة أساسية تعتمد عليها أثناء تصميم تطبيق اتك‪.‬‬ ‫‪ -4‬لغة قوية ومرنة‪ :‬ق لنا سابق ا ال حدود لهذه اللغة فقط أطلق العنان لخيالك فيمكننا استخدام لغة السي شارب في المشاريع‬ ‫الكبيرة ذات األشكال المتعددة كالبرامج الرسومية وجداول البيانات وبرامج ‪ compilers‬للغات أخرى‪.‬سنتعرف على الكلمات األساسية الحق ا‪.NET‬وإذا كنت مبرمجا بإحدى لغات البرمجة‬ ‫التي ال تدعم البرمجة كائنية التوج ه ف إننا قد أفردنا جزءا كامال في هذا الكتاب لن يعلمك مف اهيم البرمجة كائنية التوجه‬ ‫في ‪ .‬‬ ‫‪ -6‬لغة نمطية‪ :‬األوامر في ‪ C#‬تكتب على شكل ‪ Classes‬أي أصناف وتحتوي على أساليب العضو وهذه األصناف يمكن‬ ‫إعادة استخدامها في برامج أخرى‪.‬‬ ‫ويكفي أن نقول إنك بواسطة لغة ‪ C#‬ستتمكن من تصميم أعقد التطبيق ات وبمجهود أق ل بكثير من الذي يمكن أن تبذله‬ ‫باستخدام لغات برمجة أخرى‪.‬‬ ‫لمن هذا الكتاب؟‬ ‫يستهدف هذا الكتاب األشخاص الذين يودون تعلم البرمجة ويودون البدء بلغة برمجية جديدة ويستهدف أيضا المبرمجين‬ ‫المبتدئين الذين يرغبون تطوير التطبيق ات بواسطة لغة ‪ C#‬أما بالنسبة لألشخاص الذين سبق وأن تعلموا لغة برمجية سهلة مثل‬ ‫‪ Visual Basic‬ف إن هذا الكتاب هو وسيلتهم الحتراف لغة ‪.NET‬يمثل ثورة برمجية بحد ذاته ويدخل عددا من المف اهيم الجيدة على عالم البرمجة‬ ‫هذا ويقدم الكتاب المف اهيم البرمجية كائنية التوجه المتعلقة بإطار عمل ‪ .C#‬‬ ‫وكخالصة‪ :‬ف إن هذا الكتاب موجه إلى كل شخص سأم من الكتب التي تتناول لغة ‪ C#‬سواء العربية أو حتى األجنبية والتي تفترض‬ ‫منه معرفة مسبقة بلغة برمجية أخرى‪.‫‪ -3‬لغة برمجة كائنية التوجه‪ :‬لكي تكون لغة البرمجة كائنية البد لها من مف اهيم أساسية تتصف بها وهي الكبسلة‬ ‫‪capsulation‬والتوارث ‪ Inheritance‬وتعدد األوجه‪ Polymorphism‬تدعم لغة السي شارب كل هذه‬ ‫المف اهيم وسنتعرف عل ى كل هذه المف اهيم في الدروس المتقدمة‪.‬‬ ‫قد تعتقد أن اللغة ذات العديد من الكلمات األساسية هي لغة قوية ولكن هذا غير صحيح فعندما تقوم بالبرمجة‬ ‫باستخدام لغة ‪ C#‬ستجد أنها لغة يمكن استخدامها في أداء أي مهمة‪ .NET‬وحسب وإنما إتق ان هذه المف اهيم أيضا‪.‬‬ ‫ما الذي تحتاج إليه الستخدام هذا الكتاب؟‬ ‫‪.

NET 2013‬‬ ‫أصدرت شركة ‪ Microsoft‬ثالث نسخ من ‪ Visual Studio.‬‬ ‫تحميل نسختك من ‪:Visual Studio.NET 2013‬وهي‪:‬‬ ‫‪ Visual Studio Express 2013 -1‬وهي نسخة مجانية‪.NET‬والتي‬ ‫يمكنك جلبها من موقع شركة ‪Microsoft‬‬ ‫ولكن كي تتمكن من االستف ادة القصوى من هذا الكتاب ف أنت بحاجة إلى بيئة التطوير المتكاملة ‪Visual Studio.NET‬‬ ‫‪ 2013‬والتي تبسط عليك كتابة شيفرة ‪ C#‬من عدة جوانب كما أنها مفيدة جدا وربما أساسية لتطوير تطبيق ات ‪Windows‬‬ ‫وذلك ألنها تحوي على مصمم مرئي للنماذج يحول تصميم واجهات المستخدم إلى متعة حقيقة‪.‫إن أهم ما تحتاج إليه الستخدام هذا الكتاب هو مترجم ‪ C#‬يمثل المترجم ‪ Compiler‬األداة التي ستحو ل شيفرتك المكتوبة بلغة‬ ‫‪ C#‬إلى برنامج تنفيذي ويأتي هذا المترجم كجزء من مجموعة تطوير إطار عمل ‪ ).11 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .NET Framework SDK( .‬‬ ‫‪.

‫‪ Visual Studio Professional 2013 -0‬وهي نسخة مدفوعة الثمن‪.12 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .‬‬ ‫‪ Visual Studio Ultimate 2013 -3‬وهي نسخة مدفوعة الثمن‪.‬‬ ‫‪.

NET‬مخصص لتطوير جميع أنواع التطبيقات من تطبيقات أنظمة التشغيل إلى‬ ‫تطبيقات االنترنت وخدمات ويب ( ‪ )Web Services‬وتطبيقات أخرى يمكننا تصميمها‬ ‫بواسطتها‪.Windows‬‬ ‫‪ -2‬إن إطار عمل ‪ .‬‬ ‫‪ -3‬إن إطار عمل ‪ . ‫الفصل األول‬ ‫مدخل إىل لغة ‪C#‬‬ ‫أهال بك في الفصل األول من هذا الكتاب سوف نلقي نظرة في هذا الفصل على بعض المعلومات األساسية‬ ‫التي نحن بحاجة إليها لالنطالق مع لغة ‪ .NET‬حيث أن إطار عمل ‪ .NET‬فإنها يمكن أن تتواصل مع بعضها البعض أيضا مما يمكن تكوين فريق برمجي‬ ‫‪.C++‬‬ ‫وأخيرا سنلقي نظرة سريعة على أداة التطوير التي سنستخدمها خالل هذا الكتاب وهي ‪Visual‬‬ ‫‪.‬‬ ‫سنبدأ أوال مع وصف عام إلطار عمل ‪ .NET‬السابق النقاط التالية‪:‬‬ ‫‪ -1‬ان إطار عمل ‪.NET‬صمم بطريقة تسمح باستخدامه من خالل اية لغة برمجة فيمكننا استخدام‬ ‫إطار عمل ‪ .NET‬منصة جديدة ونقلة نوعية تم تطويرها من قبل شركة ‪ Microsoft‬بهدف تطوير‬ ‫التطبيقات‪.NET‬وكيفية ارتباط هاتين التكنولوجيتين ببعضهما البعض‪.‬‬ ‫بعد أن نتناول إطار عمل ‪ .‬‬ ‫يمكننا أن نستشف من تعريف إطار عمل ‪ .NET‬موجه لتطوير التطبيقات لجميع أنظمة التشغيل وليس حكرا على تطوير‬ ‫تطبيقات أنظمة التشغيل ‪.C#‬سوف نتناول لغة ‪ C#‬في هذا الفصل بإيجاز‪ ،‬باإلضافة إلى‬ ‫إطار عمل ‪ )NET Framework( .NET‬سننتقل لشرح بسيط عن لغة ‪ C#‬حيث سنقدم الجذور التي نشأت منها‬ ‫تلك اللغة وأوجه التشابه بينها وبين لغة ‪.13 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .NET‬‬ ‫يمثل إطار عمل ‪ .NET‬مع لغة ‪ C#‬ولغة ‪ Visual Basic‬ولغة ‪ Jscript‬ولغة البرمجة ‪ C++‬ولغة‬ ‫البرمجة ‪ F#‬وغيرها من لغات البرمجة وباإل ضافة إلى تواصل هذه اللغات البرمجية مع إطار‬ ‫عمل ‪ .Studio.NET‬يمثل تكنولوجيا جديدة تتضمن‬ ‫العديد من المفاهيم الجديدة والتي تغير المنحى الذي اعتاد المبرمجون سلوكه في التكنولوجيا البرمجية‬ ‫السابقة‪.

‬‬ ‫يتضمن إطار عمل ‪ .)CTS( Common Type System‬‬ ‫توضيح‪:‬‬ ‫تستخدم لغات البرمجة المختلفة أنواع معطيات مختلفة فعلى سبيل المثال تستخدم لغة ‪C++‬‬ ‫نوع المعطيات ‪ int‬لمثيل القيم الصحيحة بينما تستخدم لغة ‪ Visual Basic.NET‬فإن ‪ .NET‬تسمى هذه اآللية‬ ‫ب نظام النوع المشترك ‪.NET‬مكتبة ضخمة من الشيفرة التي يمكننا استخدامها من خالل لغات البرمجة‬ ‫المتوافقة مع هذا اإلطار مثل لغة ‪ C#‬وذلك بواسطة تقنيات البرمجة كائنية التوجه ‪ OOP‬لقد صنفت هذه‬ ‫المكتبة ضمن وحدات برمجية مختلفة يعتمد تصنيفها على نوعية النتائج التي نود الحصول عليها منها‪.‫تقني أفراده كل واحد منهم متمكن من لغة برمجة مختلفة عن االخر وبالتالي يجعل الفريق البرمجي‬ ‫أكثر ديناميكية‪.NET‬يعرف بعض األنواع األساسية يمثل النوع ‪ type‬وصفا للبيانات‬ ‫وللنوع دور كبير في تسيير التشارك بين لغات البرمجة عند استخدام إطار عمل‪.NET‬نوع‬ ‫المعطيات ‪ integer‬لتمثيل القيم الصحيحة أيضا إن ما يقوم به نظام النوع المشترك ‪CTS‬‬ ‫هو توفير قاعدة مشتركة يمكن للغات البرمجة المختلفة استخدام أنواع العناصر البرمجية‬ ‫المختلفة كالمتحوالت والكائنات مع بعضها البعض والتواصل بين تلك اللغات بواسطة تلك‬ ‫القاعدة‪.14 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .NET‬‬ ‫‪.NET‬يتضمن أيضا محرك زمن تنفيذ‬ ‫اللغة المشترك ‪ )CLR( Common Language Runtime‬والذي يمثل الجزء المسؤول عن تنفيذ‬ ‫جميع التطبيقات المصممة بواسطة مكتبة ‪.‬‬ ‫وباإلضافة إلى هذا الجزء الهام من مكتبة إطار عمل ‪ .‬‬ ‫هناك جزء خاص في إطار عمل ‪ .‬‬ ‫على سبيل المثا ل هناك وحدة برمجية خاصة ببناء الكتل في تطبيقات ويندوز وهناك وحدة برمجية أخرى‬ ‫للتعامل مع الشبكات وأخرى لتطوير تطبيقات الويب وغيرها من الوحدات البرمجية وتنقسم بعض هذه‬ ‫الوحدات إلى وحدات برمجية فرعية أيضا مثل الوحدة البرمجية المستخدمة لتطوير خدمات الويب (‪Web‬‬ ‫‪ ) Services‬والتي تمثل جزء من الوحدة البرمجية المستخدمة لتطوير تطبيقات االنترنت‪.

NET 2013‬كأداة لتطوير‬ ‫التطبيقات‪.15 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .‬‬ ‫بعد ترجمة الشيفرة البرمجية إلى اللغة الوسيطة (‪ )MSIL‬سوف يتم حفظ شيفرة (‪ )MSIL‬ضمن ما‬ ‫يعرف بالمجمعة ‪ assembly‬تمثل هذه المجمعات ملفات التطبيق التنفيذية والتي يمكن أن تنقذ مباشرة‬ ‫دون الحاجة إلى تطبيقات أو أدوات أخرى (لهذه الملفات امتداد ‪ ).NET‬عبر مرحلة وسيطة‬ ‫حيث تحول فيها الشيفرة البرمجية المكتوبة بإحدى لغات البرمجة مثل ‪ Visual Basic‬أو ‪ C#‬عبر شيفرة‬ ‫وسيطة تسمى باللغة المتوسطة (‪ )Microsoft Intermediate Language‬أو تسمى اختصارا بلغة‬ ‫(‪ )MISL‬إ ن ترجمة الشيفرة البرمجية إلى لغة (‪ )MSIL‬هي مهمة بيئة التطوير المتكاملة ( ‪Visual‬‬ ‫‪ )Studio .NET‬و غيرها من لغات‬ ‫البرمجة‪.NET‬ولكن إلى االن ال يستطيع التطبيق أن ينفذ فما زالت هناك خطوة ضرورية أخرى لتنفيذ‬ ‫التطبيق‪ .‬إن هذه المرحلة هي مهمة مترجم (‪ )Just-In-Time‬أو (‪ )JIT‬والذي يقوم بترجمة لغة‬ ‫(‪ ) MSIL‬إلى لغة محلية مفهومة لنظام التشغيل والتي تسمى لغة االلة‪.exe‬وهناك نوع أخر من المجمعات‬ ‫وهي عبارة عن مكتبا ت تستخدم مع التطبيقات وتأخذ االمتداد (‪).‬‬ ‫لكي نستطيع تنقيذ شيفرة مكتوبة بلغة البرمجة ‪ C#‬يجب أن نحول هذه اللغة إلى لغة يستطيع نظام التشغيل‬ ‫فهمها وتسمى هذه اللغة باللغة المحلية (‪ )native code‬أو لغة االلة (‪ )machine code‬تسمى عملية‬ ‫التحويل تلك بالترجمة (‪ )compiling‬وهي وظيفة المترجم (‪.NET‬هي أداة تطوير متكاملة وقوية تدعم لغة البرمجة ‪ C#‬باإلضافة إلى لغات‬ ‫برمجة أخرى مثل ‪ F#‬ولغة البرمجة ‪ C++‬ولغة البرمجة ‪ Visual Basic .NET‬في هذا الكتاب سوف نستخدم ‪ Visual Studio .‬‬ ‫إن ‪ Visual Studio .‫إن كتابة شيفرة برمجية باستخدام إطار العمل ‪ .NET CLR‬مثبت على ذلك النظام‪.‬‬ ‫بالطبع ليس بالضرورة وضع كل شيء نحتاجه لعمل تطبيق في مكان واحد قد تكون لدينا شيفرة تقوم بأداء‬ ‫وظائف عدة مشتركة مع تطبيقات متعددة وفي حاالت كهذه من األفضل وضع المكونات التي يشترك في‬ ‫استخدامها عدة تطبيقات في مكان بحيث يمكن لجميع التطبيقا ت الوصول إليها يسمى هذا المكان في إطار‬ ‫‪.)compiler‬‬ ‫تمر عملية ترجمة شيفرة برمجية مكتوبة بإحدى اللغات التي تدعم إطار العمل ‪ .NET‬‬ ‫هذا يعني أن تطوير التطبيقات أصبح بسهولة نسخ الملفات إلى مجلد على جهاز الكمبيوتر وبما انه لم تعد‬ ‫هناك حاجة لمعلومات إضافية عن األنظمة التي يستهدفها التطبيق فإن بإمكاننا تشغيل الملف التنفيذي من‬ ‫هذا المجلد مباشرة بافتراض أن محرك زمن تنفيذ اللغة المشتركة ‪ .NET‬يعني كتابة شيفرة برمجية باستخدام إي لغة برمجية‬ ‫تدعم إطار العمل ‪ .‬‬ ‫والشكل (‪ )1-1‬يبين خطوات عملية الترجمة‪.dll‬‬ ‫تتضمن المجمعات معلومات وصفية ‪ metadata‬باإلضافة إلى شيفرة ‪ MSIL‬ويمكن أن تحوي مصادر‬ ‫‪ resources‬اختبارية تمثل بيانات إضافية مثل ملفات صوت أو أيقونات إن مهمة المعلومات الوصفية‬ ‫هي جعل المجمعة ذاتية الوصف بصورة تامة أي أننا لسنا بحاجة إلى اية معلومات أخرى الستخدام‬ ‫المجمعة وهذا يعني أننا لم نعد بحاجة إلى تزويد مسجل النظام بمعلومات محددة عن المكونات لنتمكن من‬ ‫استخدامها أو اإلخفاق في تشغيل التطبيق بسبب حدوث تضارب في هذه المكونات كما كانت المشكلة مع‬ ‫المكونات قبل عهد ‪.

‬‬ ‫الشكل (‪)1.16 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .1‬‬ ‫المكون هو عبارة عن برنامج فرعي أو جزء من برنامج يحوي شيفرة تنفيذية وليس شيفرة مصدرية مما‬ ‫يعني أن بإمكان البرامج األخرى أن تستخدمه دون الحاجة إلعادة ترجمة الشيفرة المصدرية ودون الحاجة‬ ‫لمعرفة الشيفرة المصدرية الخاصة بالمجمعة مما يوفر نوعا من األمن‪.‬‬ ‫مزايا المكونات‪:‬‬ ‫من أهم مزايا المكونات‪:‬‬ ‫‪ -1‬إعادة استخدام البرامج الفرعية في برامج عديدة مثال‪ :‬في حال قمت ببناء مكتبة خاصة بك‬ ‫وأردت أن تعطيها لشخص آخر دون أن يعرف ما هي الخوارزميات المتبعة في كتابة الكود‬ ‫الخاص بك‪ ،‬يمكنك أن تعطيه ملف ‪ DLL‬بدال من الشيفرة المصدرية للمكتبة‪.‫عمل ‪ .‬‬ ‫‪.NET‬بذاكرة المجمعة العامة ‪ )GAC( Global Assembly Cache‬إن وضع الشيفرة البرمجية‬ ‫في هذه الذاكرة سهل للغاية ويمكننا بذلك بمجرد وضع المجمعة المشتركة ضمن المجلد الذي يمثل هذه‬ ‫الذاكرة‪.

(Stack‬‬ ‫أي أن الشيفرة المكتوبة باستخدام ‪ .NET‬‬ ‫بمعالجة أي تفاعل مع نظام التشغيل ولكن هذا ال يعني أننا لن نتمكن من استخدام الوظائف منخفضة‬ ‫المستوى في لغة ‪ C#‬كالوصول المباشر إلى الذاكرة وإنما يمكننا ذلك من خالل ما يسمى بالشيفرة غير‬ ‫اآلمنة ‪.NET‬مثل ‪ C#‬أنها ال تُتعب المبرمج في تفاصيل إدارة‬ ‫الذاكرة وكيفية حجز األغراض وتحريرها وعلى وجه الخصوص جامع النفايات ‪Collector Garbage‬‬ ‫والذي يوفر على المبرمج عناء تحرير المناطق المحجوزة من قبل البرنامج في الذاكرة وبالنتيجة الحصول‬ ‫على لغة تملك من الفعالية ما يؤهلها لمنافسة لغة ‪ C++‬من دون الخوض في تفاصيل إدارة الذاكرة ‪.‬‬ ‫‪.‫‪ -2‬المجمعة التي قمت ببنائها يمكنك أن تقوم ببيعها‪ ،‬ويمكنك أن توقعها باسم فريد يُسمى ‪Strong‬‬ ‫‪ Name‬لتكون وحيدة على مستوى العالم ولحفظ حقوقك من السرقة أو االستخدام غير المشروع‪.‬لكن‬ ‫إذا أردنا ان نكتب شيفرة فعالة وسريعة فإنه يجب علينا أن يكون لدينا نظرة عامة عن طريقة حجز الذاكرة‬ ‫ضمن الحاسب‪.17 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .NET‬تؤمن لنا ما‬ ‫يسمى بالشيفرة المدارة ( ‪ )managed cod‬وهذه الشيفرة تحظر علينا التعامل بشكل مباشر مع الذاكرة‬ ‫من خالل ما يُعرف بالمرجع (‪ )Reference‬إال أننا وفي بعض األحيان قد نضطر إلى التعامل بشكل‬ ‫مباشر مع الذاكرة وبالتالي ينبغي علينا فهم المبادئ األساسية ال ُمستخدمة لكيفية حجز المساحات ضمن‬ ‫المنطقة ‪( Heap‬تسمى الكومة) وضمن المكدس )‪.NET‬تكون مدارة عند تنفيذها أي أنها تخضع لإلدارة من قبل محرك‬ ‫‪ CLR‬الذي ال يهتم بالتطبيق أثناء التنفيذ وحسب وإنما يعالج مواضيع عدة مثل إدارة الذاكرة ومعالجة‬ ‫المسائ ل المتعلقة بأمن التطبيق والسماح بالتنقيح متداخل اللغات وغير ذلك وبالمقابل تسمى شيفرة‬ ‫التطبيقات التي ال تخضع للسيطرة من قبل محرك ‪ CLR‬بالشيفرة غير المدارة ‪Unmanaged code‬‬ ‫وتُعتبر لغتي ‪ C/C++‬هي من أهم اللغات التي تبني تطبيقات بشيفرة غير مدارة وذلك بهدف الوصول‬ ‫إلى الوظائف منخفضة المستوى لنظام التشغيل أما في لغة ‪ C#‬فإنه ال يمكننا كتابة إال شيفرة برمجية‬ ‫مدارة فقط وبالتالي فإنها تستفيد من مزايا اإلدارة الموجودة في ‪ CLR‬والسماح الطار عمل ‪.unsafe code‬‬ ‫أحد أهم مزايا اللغات التي تعمل تحت منصة ‪ .‬‬ ‫أي أن مجمع نفايات ‪ .NET‬يعمل على مراقبة الذاكرة التي يحتلها التطبيق ويقوم بمتابعة وإزالة أية بيانات‬ ‫من الذاكرة لم يعد التطبيق بحاجة لها‪.‬‬ ‫تُعتبر إدارة الذاكرة من أهم المواضيع التي على المبرمج المحترف أن يتقنها مع أ ن ‪ .

18 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .NET‬بالخطوات التالية‪:‬‬ ‫كتابة شيفرة التطبيق بإحدى لغات البرمجة التي تدعم إطار العمل ‪ .‬‬ ‫تسمى هذه العملية بالربط (‪ )Linking‬وهي مفيدة للغاية وذلك لعدة أسباب أهمها‪:‬‬ ‫‪ -1‬سهولة العمل مع ملفات صغيرة بدال من العمل مع ملف واحد كبير‪.JIT‬‬ ‫‪-3‬‬ ‫ستنفذ الشيفرة المحلية بتحكم من ‪ CLR‬مع التطبيقات األخرى المنفذة‪.‬‬ ‫‪-2‬‬ ‫عند تنفيذ الشيفرة يجب أن تترجم أوال إلى لغة محلية وذلك بواسطة مترجم ‪.‬‬ ‫‪-4‬‬ ‫إن شيفرة ‪ C#‬التي تمت ترجمتها إلى لغة ‪ MSIL‬ليست بحاجة ألن تكون موجودة ضمن ملف وحيد فمن‬ ‫الممكن توزيع شيفرة التطبيق الواحد على ملفات متعددة حيث يتم ترجمة هذه الملفات مع بعضها البعض‬ ‫ضمن مجمعة وحيدة‪.NET‬‬ ‫إن تصميم التطبيقات بواسطة لغة ‪ C#‬أسهل من تصميمها بواسطة لغة ‪ C++‬وذلك باعتبار ان الصيغ‬ ‫المستخدمة فيها أبسط إن لغة ‪ C#‬هي لغة برمجة قوية وهناك القليل من األشياء التي يمكنك القيام بها في‬ ‫‪ C++‬وال يمكنك ذلك في ‪ C#‬في الحقيقة يمكننا القيام بالمزايا المتقدمة التي توفرها لغة ‪ C++‬مثل‬ ‫الوصول والتعامل المباشرين مع الذاكرة ضمن ‪ C#‬وذلك بواسطة الشيفرة غير اآلمنة ‪unsafe code‬‬ ‫‪. ‫تتلخص خطوات إنشاء تطبيق في ‪ .NET‬فهذه اللغة تمثل‬ ‫نقلة متطورة ومدروسة للغتي ‪ C‬و‪ C++‬ولغة ‪ Visual Basic‬وقد صممت من قبل شركة ‪Microsoft‬‬ ‫للعمل خصيصا على منصة ‪.C#‬‬ ‫‪-1‬‬ ‫ترجمة الشيفرة إلى لغة ‪ MSIL‬والتي سيتم حفظها ضمن المجمعة‪.‬‬ ‫‪ -2‬توزيع المهام البرمجية على عدة مطورين بحيث يمكن لكل مطور العمل بصورة منفصلة عن‬ ‫االخر مما يوفر مرونة أكبر في تصميم التطبيقات من قبل فريق من المطورين الذين توزع عليهم‬ ‫مهام البرمجة‪.‬‬ ‫وهي إحدى لغات البرمجة التي تستخدم لتطوير التطبيقات التي تعمل ضمن بيئة ‪ .NET‬مثل ‪.

)ADO.‬‬ ‫سوف نستخدم في هذا الكتاب بيئة التطوير المتكاملة ‪ Visual Studio .‫إن هذه التقنية البرمجية المتقدمة خطيرة باعتبار أنه من المحتمل الكتابة فوق كتل من الذاكرة يستخدمها‬ ‫النظام أو تستخدمها تطبيقات أخرى مما يؤدي إلى نتائج وخيمة كانهيار نظام التشغيل ولهذا السبب‬ ‫وألسباب عدة أيضا فإ ننا لن نتناول موضوع شيفرة ‪ C#‬غير اآلمنة في هذا الكتاب ألنه موضوع متقدم‪.NET‬ويتم ذلك بواسطة الوحدة البرمجية ‪.‬‬ ‫ويمكن تحقيق هذه التطبيقات من خالل تقنية ( ‪ )Active Data Objects.NET‬والتي تمثل مكتبة ضخمة من عناصر التحكم ‪ Controls‬مثل أزرار األوامر وأشرطة األدوات‬ ‫والقوائم يمكن أن نستخدمها لبناء واجهة المستخدم ‪.Web Forms‬‬ ‫خدمات ويب‪ :‬وهي التطبيقات التي تمكننا من تبادل أي نوع من البيانات ظاهريا عبر شبكة االنترنت‬ ‫باستخدام صيغة بسيطة وذلك بغض النظر عن اللغة البرمجية المستخدمة إلنشاء خدمة ويب أو النظام‬ ‫الذي تعمل الخدمة من خالله‪.‬‬ ‫‪.NET‬أو (‪.NET‬وتدعى اختصارا بـ‬ ‫(‪ )ASP.‬‬ ‫ليست هناك قيود على انواع التطبيقات التي يمكننا إنشائها بواسطة لغة ‪ C#‬حيث تستخدم هذه اللغة إطار‬ ‫عمل ‪ .NET‬‬ ‫هناك أشكال أخرى من التطبيقات التي يمكن تحقيقها أيضا بواسطة إطار عمل ‪ .NET‬مثل إنشاء مكونات‬ ‫الشبكات أو إخراج الرسوميات وتنفيذ المهام الرياضية والتحليلية المعقدة وغيرها من المهام والمتطلبات‬ ‫التطبيقية االخرى‪.NET‬ومن أهم التطبيقات التي يمكن تطويرها باستخدام لغة ‪:C#‬‬ ‫تطبيقات ‪ :Windows‬وهي التطبيقات الموجهة لنظام التشغيل ويندوز مثل برنامج ‪Microsoft‬‬ ‫‪ Office‬يمكننا إنشاء هذه التطبيقات بواسطة الوحدة البرمجية ‪ Windows Forms‬في إطار عمل‬ ‫‪ .NET 2013‬التي طورتها شركة‬ ‫‪ Microsoft‬وذلك إلنشاء أنواع التطبيقات السابقة بدء من تطبيقات سطر االوامر ذات الواجهة البسيطة‬ ‫ووصوال إلى مشاريع أكثر تطورا‪.user interface‬‬ ‫تطبيقات ويب‪ :‬مثل تصميم صفحات االنترنت وتصميم تطبيقات االنترنت كبرامج المتصفحات وغيرها‬ ‫والتي تسمى بصفحات المخدم النشط ( ‪ )Active Server Pages.19 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .

NET 2013‬العديد من المعالجات المساعدة ‪ Wizards‬التي تقوم‬ ‫‪-5‬‬ ‫بأتمتة المهام شائعة االستخدام تقوم هذه المعالجات المساعدة في الغالب بإضافة شيفرة لملفات‬ ‫موجودة مسبقا بعد أن تطلب منك إتباع عدد من الخطوات الواضحة لتحقيق المهمة المطلوبة منها‪.‬‬ ‫يتضمن ‪ Visual Studio .‬‬ ‫يتضمن مصممات لتطبيقات ‪ Windows Forms‬و ‪ Web Forms‬بمزايا سحب واسقاط‬ ‫‪-3‬‬ ‫عناصر التحكم على نموذج واجهة المستخدم‪.‫لم يصمم ‪ Visual Studio .‬‬ ‫يتضمن ‪ Visual Studio .‬‬ ‫‪.NET 2013‬يقوم بكتابة هذه الشيفرة وتوفيرها لنا بصورة مباشرة مما يقلص الزمن‬ ‫المستغرق للبدء بالمشروع‪.‬‬ ‫استخدام تقنيات متقدمة لتنقيح األخطاء (‪ )debugging‬عند تطوير المشاريع كإمكانية االنتقال‬ ‫‪-8‬‬ ‫في تنفيذ التطبيق خطوة بخطوة‪ ،‬بينما نركز في أثناء ذلك على حالة التطبيق‪.NET 2013‬أتمته الخطوات المطلوبة لترجمة الشيفرة المصدرية‬ ‫‪-1‬‬ ‫وإعطاء المطور تحكما كامال بأية خيارات مستخدمة لذلك في نفس الوقت‪.‬‬ ‫يتضمن ‪ Visual Studio .‬‬ ‫يتضمن محرر نصوص ذكي لكتابة الشي فرة المصدرية فهو يستشعر أخطاء كتابة الشيفرة بذكاء‬ ‫‪-2‬‬ ‫ويقترح الحلول الصائبة وكل ذلك أثناء كتابتنا للشيفرة‪.‬‬ ‫هناك العديد من أنواع المشاريع التي يمكن تطويرها بلغة ‪ C#‬والتي تحتاج إلى شيفرة تحضيرية‬ ‫‪-4‬‬ ‫ثابتة وبدال من كتابة هذه الشيفرة في كل مرة نقوم فيها بإنشاء مشاريع جديدة فإن ‪Visual‬‬ ‫‪ Studio .)Notepad‬‬ ‫سوف نسرد هنا بعضا من النقاط الرئيسية والمزايا التي تجعل من ‪Visual Studio .NET 2013‬لتطوير تطبيقات ‪ C#‬بشكل حصري وإن تطوير التطبيقات‬ ‫بواسطة بيئة التطوير المتكاملة التي يوفرها يجعل من البرمجة أمرا سهال جدا بالمقارنة مع كتابة الشيفرة‬ ‫المصدرية للتطبيق ككل بواسطة محرر نصوص عادي (مثل برنامج المفكرة ‪.20 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .NET‬‬ ‫يستطيع ‪ Visual Studio .NET 2013‬أداة لنشر المشروع على شكل تطبيق جاهز لالستخدام‬ ‫‪-7‬‬ ‫النهائي‪.NET 2013‬العديد من االدوات القوية الستعراض عناصر‬ ‫‪-6‬‬ ‫المشروع واالنتقال ف يما بينها كانت هذه العناصر عبارة عن ملفات تحوي شيفرة برمجية أو‬ ‫مصادر أخرى كملفات رسومية أو ملفات صوتية‪.NET 2013‬‬ ‫االختيار الصائب لتطوير تطبيقات ‪.

NET‬ولغة ‪ C#‬وما هي الفوائد التي نجنيها من استخدام الشيفرة المدارة‬ ‫(‪.NET‬في هذا الفصل بصورة عامة وناقشنا كيف يجعل ‪ .‫لقد تحدثنا عن إطار عمل ‪ .NET‬من تطوير‬ ‫التطبيقات أمرا أسهل بكثير وأكثر مرونة من السائق لقد تعرقنا أيضا على أنواع التطبيقات التي يمكننا‬ ‫تطويرها بواسطة إطار عمل ‪ .NET‬وشرحنا األداة التي ستستخدمها لتطوير‬ ‫تطبيقات ‪ C#‬أال وهي ‪.)managed code‬‬ ‫لقد تعرقنا على لغة ‪ C#‬ومدى ارتباطها بإطار عمل ‪ .NET‬‬ ‫‪.Visual Studio .21 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .

NET‬لقد حان الوقت لكتابة بعض‬ ‫الشيفرات البرمجية‪.NET 2013‬هو برنامج معقد وضخم ويمكن أن يرهب المستخدمين المبتدئين‬ ‫للوهلة االولى إال أن استخدامه لتطوير التطبيقات أسهل بكثير من استخدام أية برامج أو أدوات أخرى‪.‬‬ ‫إن ‪ Visual Studio .‬‬ ‫سوف نستخدم برنامج ‪ Visual Studio .22 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .‬‬ ‫‪.C#‬‬ ‫بعد أن نلقي نظرة سريعة على ‪ VS‬سنقوم بإنشاء تطبيقين بسيطين بواسطته لن نركز في هذا الفصل على‬ ‫الشيفرة البرمجية للتطبيقين و إنما سنحاول إيضاح كيف ستظهر مشاريعك البرمجية بلغة ‪ C#‬في ‪.‬‬ ‫بعد أن نبدأ باستخدام ‪ VS‬في هذا الفصل سنجد أنه من غير الضروري االحاطة بكل تفاصيل هذا البرنامج‬ ‫كي نتمكن من كتابة شيفرة برمجية بلغة ‪.‬‬ ‫إن التفاصيل االضافية لتطبيقات ‪ Windows‬ليست ضرورية لتعلم لغة ‪ C#‬فتطبيقات ‪ Console‬تجعلنا‬ ‫نركز على تعلم الصيغ البرمجية بدال من االهتمام بمظهر وواجهة التطبيق‪.VS‬‬ ‫التطبيق األول الذي سنقوم بإنشائه هنا يمثل تطبيق ‪ Console‬بسيط أن تطبيقات ‪ Console‬هي تلك‬ ‫التطبيقات التي ال تستخدم واجهات نظام ‪ Windows‬الرسومية وبالتالي لن يكون هناك أزرار أوامر أو‬ ‫قوائم أو أي اهتمام بمؤشر الفأرة (‪ )mouse pointer‬في هذه التطبيقات وبدال من ذلك فإن تطبيقنا سيعمل‬ ‫ضمن نافذة سطر األوامر فقط (مثل برامج نظام التشغيل ‪. ‫الفصل الثاني‬ ‫كتابة برنامج بلغة ‪C#‬‬ ‫بعد أن ألقينا نظرة سريعة على لغة ‪ C#‬ومدى ارتباطها بإطار عمل ‪ .‬‬ ‫سوف نستخدم نوعي التطبيقات ( ‪ Console‬و ‪ )Windows Forms‬خالل الجزء الثاني والثالث من‬ ‫هذا الكتاب‪.‬‬ ‫وبالتالي فإن أول ما سنقوم به هو القاء الضوء على بعض أساسيات بيئة التطوير تلك‪.)DOS‬‬ ‫أما التطبيق الثاني في هذا الفصل فسيمثل تطبيق ‪ Windows Forms‬إن هذا النوع من التطبيقات يظهر‬ ‫مشابها من حيث واجهة استخدامه لمعظم تطبيقات ‪ Windows‬األخرى وعلى الرغم من أن برمجة هذا‬ ‫النوع من التطبيقات يتطلب صيغا أكثر تعقيدا من تلك المستخدمة لتطوير تطبيقات ‪ Console‬إال أن انشاء‬ ‫هذا النوع من التطبيقات لن يستغرق منك الكثير من العناء‪.NET 2013‬أو اختصارا ‪ VS‬لكتابة تطبيقات ‪ C#‬خالل هذا‬ ‫الكتاب‪.

‬‬ ‫‪.‬‬ ‫الشكل (‪)2.‬‬ ‫الشاشة الرئيسية‪ :‬وهي أهم منطقة في ‪ VS‬ألنها منطقة العمل الفعلية حيث تظهر فيها‬ ‫‪-5‬‬ ‫العناصر المكونة لمشروعك والكود المرافق لها‪.‬‬ ‫القوائم وشريط األدوات‪ :‬كل الخصائص واالمكانيات الموجودة في ‪ VS‬يمكنك التحكم بها‬ ‫‪-4‬‬ ‫بثالث طرق إما عن طريق القوائم أو األدوات العلوية األزرار أو االختصارات‪.‫إن بيئة التطوير المتكاملة التي سنبني عليها مشاريعنا في هذا الكتاب هي ‪Microsoft Visual Studio‬‬ ‫‪ Ultimate 2013‬عند تشغيل هذا البرنامج سوف تظهر لدينا نافذة البرنامج كما في الشكل (‪)2-1‬‬ ‫فكما يظهر في الشكل فإن هذا البرنامج يحوي على مجموعة من القوائم المنسدلة كما في أغلب تطبيقات‬ ‫ويندوز وسوف نتحدث عن باقي العناصر في المستقبل وما المهمة الموكلة لكل منها‪.23 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .‬‬ ‫صندوق األدوات‪ :‬هذا الصندوق يحوي كل األدوات التي تحتاجها في برنامجك كصناديق‬ ‫‪-3‬‬ ‫النصوص واألزرار والقوائم وغيرها‪.‬‬ ‫نافذة الخصائص‪ :‬عند تحديد أي عنصر في الصفحة الرئيسية أو في نافذة مستكشف الحلول فإن‬ ‫‪-2‬‬ ‫خصائص هذا الكائن تظهر هنا ويمكن تعديلها بسهولة‪.1‬‬ ‫مستعرض الحلول أو العناصر‪ :‬يظهر في هذا القسم جميع مكونات الحل ‪ Solution‬والذي‬ ‫‪-1‬‬ ‫يحوي على مشروع ‪ Project‬أو أكثر وكل مشروع يتكون من عدة عناصر كالنماذج ‪Forms‬‬ ‫والمكتبات ‪ Classes‬وغيرها‪.

2‬‬ ‫نختار من القائمة المنسدلة ‪ installed‬على يسار النافذة الخيار ‪ Visual C#‬ومن النافذة المتوسطة نختار‬ ‫‪ Console Application‬ونختار من القاتمة المنسدلة في الوسط اصدار ‪ . ‫‪ -6‬نافذة الخرج‪ :‬سوف نتحدث عنها الحقا‪.‬‬ ‫سوف نستخدم تطبيقات كونسول باستمرار في هذا الكتاب وكبداية سنقوم بإنشاء تطبيق ‪ Console‬بسيط‪.NET Framework‬الذي‬ ‫نريد بناء التطبيق تحت منصته ويفضل اختيار أحدث اصدار وهو مختار بشكل افتراضي من قبل البرنامج‬ ‫ثم نقوم بتغيير اسم التطبيق ام الخانة ‪ Name‬إلى االسم ‪ Console hello world‬ثم نختار مكان حفظ‬ ‫المشروع بالضغط على الزر ‪ Browser‬ثم نضغط على زر ‪ ok‬فيظهر لنا الشكل (‪:)2-3‬‬ ‫‪.‬‬ ‫من نافذة بيئة ‪ VS‬كما في الشكل (‪ )2-1‬نضغط على الرابط ‪ New project‬من النافذة ‪ Start Page‬أو‬ ‫من القائمة المنسدلة ‪ FILE‬في شريط القوائم المنسدلة نختار االمر ‪ New project‬فتظهر لدينا النافذة‬ ‫كما في الشكل (‪.)2-2‬‬ ‫الشكل (‪)2.24 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .

3‬‬ ‫االن نأتي لمرحلة كتابة الشيفرة البرمجية لكن اين نكتب الشيفرة وماذا سنكتب ال تقلق سنتعلم كل ذلك‬ ‫فال تستعجل‪. ‫الشكل (‪)2.‬‬ ‫ان الشكل (‪ )2-3‬يظهر اربعة نوافذ وشريط القوائم المنسدلة اين سيتم كتابة البرنامج‪:‬‬ ‫ان النافذة المسماة ‪ Solution Explorer‬تظهر قائمة بالملفات المكونة للبرنامج أما النافذة ‪Properties‬‬ ‫فهي تظهر خصائص االدوات وسوف نستخدمها في تطبيقات ‪ Windows Forms‬بشكل كبير أما النافذة‬ ‫المسماة ‪ Error List‬فهي تظهر قائمة االخطاء البرمجية التي نرتكبها أثناء كتابة البرنامج فكما قلنا سابقا‬ ‫محرر نصوص ذكي يكتشف االخطاء‪.4‬‬ ‫‪.cs‬وهذه النافذة هي مبتغانا لكتابة الشيفرة البرمجية كما‬ ‫يظهر في هذه النافذة هناك الكثير من التعليمات البرمجية الموجودة سابق بشكل افتراضي فاين سنكتب‬ ‫شيفرتنا انظر للشكل (‪ )2-4‬لتعرف أين سنكتب شيفرتنا البرمجية‪:‬‬ ‫الشكل(‪)2.25 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .‬‬ ‫يتبقى لدينا النافذة الرابعة المسماة ‪ Program.

26 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .WriteLine("HELLO WORLD‬‬ ‫لتمكين المستخدم من قراءة النص الظاهر على شاشة الكونسول ‪//‬‬ ‫.Blue‬‬ ‫‪.Blue‬‬ ‫لغيير لون النص لألحمر ‪//‬‬ ‫.Read‬‬ ‫انتبه أن النص المسبوق بشرطتين ‪ //‬هو ليس نص برمجي انما هو تعليق يوضح ما تقوم به التعليمات‬ ‫البرمجية واضافة الشرط تين ‪ //‬ضروري جدا كي ال يحدث خطأ في البرنامج االن نأتي للمرحلة االخيرة‬ ‫من بناء التطبيق وهي مرحلة االختبار‪.5‬‬ ‫نأتي االن إلى مرحلة حفظ المشروع نختار من القائمة المنسدلة ‪ FILE‬االمر ‪.)"‪Console.)(‪Console.‪Console.)2-5‬‬ ‫الشكل (‪)2.Red‬‬ ‫إلظهار نص معين على شاشة الكونسول ‪//‬‬ ‫.‪Console.ForegroundColor = ConsoleColor.Save all‬‬ ‫نعود األن إلى شيفرة البرنامج ونقوم بحذف الفاصلة المنقوطة من نهاية أي سطر نريد وليكن من السطر‬ ‫الذي يحوي الشيفرة التالية‪:‬‬ ‫‪Console.BackgroundColor = ConsoleColor.BackgroundColor = ConsoleColor. ‫واالن قم بكتابة الشيفرة البرمجية التالية‪:‬‬ ‫لجعل الخلفية زرقاء ‪//‬‬ ‫.‬‬ ‫هناك عدة طرق الختبار البرنامج اما بالضغط على زر ‪ F5‬من لوحة المفاتيح او بالضغط على زر ‪Start‬‬ ‫الظاهر أسفل شريط القوائم المنسدلة أو من القائمة المنسدلة ‪ DEBUG‬نختار االمر ‪Start Debugging‬‬ ‫فيظهر لدينا الشكل (‪.

7‬‬ ‫‪ -3‬فعل الخانة المالصقة لـ ‪ Line numbers‬ثم انقر على زر ‪ ok‬ستالحظ عندئذ ترقيم أسطر‬ ‫الشيفرة بصورة تلقائية‪.6‬‬ ‫بالنفر المزدوج على رسالة الخطأ نالحظ ان المؤشر يذهب إلى مكان الخطأ كما أن الرسالة تبين لنا نوع‬ ‫الخطأ المرتكب وهو نقصان الفاصلة المنقوطة الحظ أنه تم تحيد الخطأ بناء على رقم السطر كما أن أرقام‬ ‫االسطر ال تعرض بشكل افتراضي في محرر نصوص ‪ VS‬للقيام بذلك اتبع الخطوات التالية‪:‬‬ ‫‪ -1‬اختر االمر ‪ Option‬من القائمة المنسدلة ‪ TOOL‬سيظهر عندئذ صندوق الحوار ‪.‬‬ ‫‪.27 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .Option‬‬ ‫‪ -2‬انقر على البند ‪ Text Editor‬في شجرة العناصر الموجودة على يسار صندوق الحوار ثم اختر‬ ‫‪ C#‬سيظهر لك شكل مشابه للشكل (‪. ‫نالحظ أن نافذة ‪ Error List‬قد اظهرت رسالة تشير إلى وجود خطأ ما في السطر ذي الرقم ‪ 14‬كما‬ ‫في الشكل (‪:)2-6‬‬ ‫الشكل(‪)2.)2-7‬‬ ‫الشكل (‪)2.

400‬‬ ‫‪startposition‬‬ ‫‪CenterScreen‬‬ ‫‪Text‬‬ ‫ترحيب‬ ‫‪.‫لن نتعلم في هذا المثال سوى أساسيات بناء تطبيقات ‪ Windows Forms‬ويتم ذلك وفقا للخطوات التالية‪:‬‬ ‫‪ -1‬اضغط على ‪New Project‬‬ ‫‪ -2‬قم باختيار الخيار ‪Windows Forms Application‬‬ ‫‪ -3‬غير االسم ‪ Name‬إلى ‪ windows hello world‬ثم اضغط على الزر ‪ ok‬فيظهر لدينا الشكل‬ ‫(‪.)2-8‬‬ ‫الشكل (‪)2.8‬‬ ‫‪ -4‬نقوم بضبط خصائص ‪ Form1‬من نافذة ‪ Properties‬المحددة بإطار أحمر في الصورة وفقا‬ ‫للجدول التالي‪:‬‬ ‫‪Object‬‬ ‫‪Property‬‬ ‫‪Setting‬‬ ‫‪Name‬‬ ‫‪frmhello‬‬ ‫‪Icon‬‬ ‫‪shield_green‬‬ ‫‪RightToLeft‬‬ ‫‪yes‬‬ ‫‪Form‬‬ ‫‪RightToLeftLayout‬‬ ‫‪True‬‬ ‫‪Size‬‬ ‫‪400 .28 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .

99‬‬ ‫‪Font‬‬ ‫.Show("HELLO WORLD‬‬ ‫}‬ ‫‪.‫‪ -5‬ننتقل بمؤشر الماوس إلى يسار نافذه البرنامج فيظهر لدينا صندوق أدوات البرنامج ‪Toolbox‬‬ ‫نقوم باختيار البند ‪ Windows Forms‬ثم انتقل إلى العنصر ‪ Button‬وانقر عليه نقرا مزدوجا الشكل‬ ‫(‪ )2-9‬أو قم بسحب وافالته فوق ‪ Form‬ليظهر زر على ‪ Form‬باسم ‪.29 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .75pt‬‬ ‫‪Text‬‬ ‫اضغط هنا‬ ‫‪style=Bold‬‬ ‫‪ -7‬ا نقر نقرا مزدوجا على الزر الذي تمت إضافته إلى النموذج عندئذ سيتم عرض محرر الشيفرة‬ ‫ويتضمن شيفرة ‪ C#‬لهذا النموذج (أي للملف ‪.Button1‬‬ ‫الشكل (‪)2.)"‪MessageBox.‪T imes New Roman.cs‬‬ ‫‪ -8‬اكتب الشيفرة التالية كما كتبناها سابقا في تطبيق ‪( Console‬لم نذكر هنا إال جزء من الشيفرة‬ ‫الموجودة في الملف فقط وذلك لالختصار ال أكثر)‪:‬‬ ‫)‪private void buthello_Click(object sender.)Form1. 15.9‬‬ ‫‪ -6‬نقوم بالضغط على ‪ Button1‬مرة واحة فتظهر خصائص ‪ Button‬نقوم بضبطها كما في‬ ‫الجدول التالي‪:‬‬ ‫‪Object‬‬ ‫‪Property‬‬ ‫‪Setting‬‬ ‫‪Button‬‬ ‫‪Name‬‬ ‫‪buthello‬‬ ‫‪Size‬‬ ‫‪145 . EventArgs e‬‬ ‫{‬ ‫.

11‬‬ ‫كيفية العمل‪:‬‬ ‫‪How it Works:‬‬ ‫ومجددا نقول أن ‪ VS‬قام بجل العمل عوضا عنا و قد سهل علينا لدرجة كبيرة إنشاء تطبيقات ‪Windows‬‬ ‫وظيفية بقليل من الجهد الحظ أن التطبيق الذي قمنا بإنشائه للتو يتصرف تماما كأي تطبيق ‪Windows‬‬ ‫أخر الحظ أننا لم نكتب أية شيفرة لتحقيق ذلك (كرسم النموذج على الشاشة و التحكم بأزرار التصغير‬ ‫و التكبير الموجودة ضمن سطر عنوان النموذج)‪.‬‬ ‫‪.)2-19‬‬ ‫الشكل (‪)2.)2-11‬‬ ‫الشكل (‪)2. ‫‪ -9‬نفذ التطبيق (وذلك بالضغط على مفتاح ‪ )F5‬عندئذ سيظهر الشكل (‪.‬‬ ‫إن األمر مشابه أيضا للزر الذي أضفناه إلى ذلك النموذج فبمجرد النقر المزدوج على الزر سيعلم ‪VS‬‬ ‫تلقائيا من أننا نود كتابة شيفرة تنفذ عند النقر على ذلك الزر أثناء تنفيذ التطبيق‪.19‬‬ ‫‪ -19‬اضغط على الزر اضغط هنا عند ئذ ستظهر الرسالة كما في الشكل (‪.30 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .

‬إن الزر الذي أضفناه في هذا المثال على النموذج يمثل واحدا من عناصر‬ ‫التحكم العديدة التي يمكننا استخدامها إن جميع عناصر التحكم التي يمكننا استخدامها في تطبيقانا هذا‬ ‫موجودة ضمن البند ‪ All Windows Forms‬في صندوق عناصر التحكم ‪Toolbox‬‬ ‫‪.31 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .‬‬ ‫ربما تكون الشيفرة البرمجية الموجودة في الملف ‪ Form1.‫وطبعا فإن تطبيقات ‪ Windows‬ليست محصورة باألزرار والنماذج فقط فإذا ألقيت نظرة على‬ ‫صندق‪ Toolbox‬ورأيت ما يتضمنه من بنود وعناصر ستلحظ عدد عناصر التحكم التي يمكننا أن‬ ‫نستخدمها في تطبيقاتنا سوف نتعلم استخدام معظم هذه العناصر في موضع ما من هذا الكتاب الحقا وسوف‬ ‫تدهش لمدى سهولة القيام بذلك‪.‬إن معظم هذه الشيفرة تركز على عناصر التحكم ( ‪ )controls‬الموجودة على النموذج وهو ما‬ ‫يعكس إمكانية عرض الشيفرة في نمط التصميم (‪ design view‬ضمن اإلطار الرئيسي والذي يمثل‬ ‫ترجمة مرئية لهذه الشيفرة التحتية (سميت بالتحتية ألنها تمثل االساس الذي سنتمكن بواسطته التعامل مع‬ ‫عناصر التحكم في النموذج)‪ .cs‬معقدة بعض الشيء بالمقارنة مع الشيفرة‬ ‫في تطبيق ‪ Console‬السابق إال أن السبب الفعلي لكونها معقدة هو عدد األسطر البرمجية المكتوبة ضمن‬ ‫الملف‪ .

‫الخالصة‪:‬‬ ‫‪Summary:‬‬ ‫لقد قدمنا في هذا الفصل بعضا من االدوات التي ستستخدمها خالل هذا الكتاب لقد أخذنا درسا سريعا عن‬ ‫بيئة تطوير ‪ Visual Studio.NET 2013‬واستخدمناها في بناء نوعين مختلفين من التطبيقات إن ابسط‬ ‫هذين التطبيقين هو تطبيق ‪ Console‬وهو يلبي متطلباتنا الحالية ويمكننا من التركيز على اساسيات‬ ‫البرمجة بلغة ‪ C#‬أما تطبيقات ‪ Windows‬أكثر جاذبية وقوة باعتبارها تعتمد على بيئة ‪Windows‬‬ ‫الرسومية‪.32 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .‬‬ ‫واالن نحن نعلم كيف نقوم بإنشاء تطبيقات بسيطة ويمكننا االنتقال إلى المهمة الحقيقية في تعلم لغة ‪C#‬‬ ‫وهو موضوع الجزء القادم من هذا الكتاب‪.‬‬ ‫‪.

)"‪("HELLO WORLD‬‬ ‫}‬ ‫الحظ أن السطر األول والثاني يمثالن تعليمة واحدة وذلك ألنه ال توجد هناك فاصلة منقوطة في نهاية‬ ‫السطر األول‪." و بما أنه سيتم تجاهل المساحة البيضاء فإنه يمكننا من أن نضع تعليمات عديدة‬ ‫صمن سطر واحد لكن و بسبب صعوبة قراءة الشيفرة عندئذ فإننا سنكتب كل تعليمة في سطر منفرد بل‬ ‫و يمكننا أن نضع التعليمة الواحدة على عدة أسطر‪.‬‬ ‫‪.‬‬ ‫للغة ‪ C#‬بنية مؤلفة من عدة كتل (‪ )Block-Structured‬وهذا يعني أن جميع التعليمات تمثل جزء من‬ ‫كتلة شيفرة تتوضع هذه الكتل ضمن األقواس }{ ويمكن أن ت تضمن أية كمية من التعليمات ويمكن أن ال‬ ‫تحوي أي تعليمة بالمرة‪.Show‬‬ ‫.‬‬ ‫و القاعدة االولى هي أن مترجم لغة ‪ C#‬ال يتأثر برموز المساحات البيضاء الزائدة في الشيفرة بعكس‬ ‫مترجمات اللغات البرمجية االخرى سواء كانت هذه المساحات عبارة عن فراغات ( ‪ )Spaces‬أو أسطر‬ ‫فارغة ( ‪ )carriage returns‬أو حتى عالمات جدولة (‪ )Tape‬هذا يعني أن لدينا الكثير من الحرية في‬ ‫الطريقة التي يمكن أن ننسق فيها شيفرتنا المصدرية على الرغم من أن اتباع اسلوب محدد سيساعد كثيرا‬ ‫على تسهيل قراءة الشيفرة تتألف شيفرة ‪ C#‬من سلسلة من التعليمات بح يث يفصل بين كل تعليمة وأخرى‬ ‫برمز الفاصلة المنقوطة ".33 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .‬‬ ‫إذا يمكننا تمثيل كتلة بسيطة من شيفرة ‪ C#‬بالشكل التالي‪:‬‬ ‫{‬ ‫‪MessageBox. ‫الفصل الثالث‬ ‫الصيغة األساسية للربجمة بلغة ‪C#‬‬ ‫تتشابه لغة ‪ C#‬من حيث الصيغة البرمجية المستخدمة ضمنها مع تلك الصيغة المستخدمة في لغتي ‪C++‬‬ ‫و‪ Java‬في البداية قد تجد هذه الصيغة مركبة نوعا ما وهي أقل قابلية للقراءة من بعض اللغات البرمجية‬ ‫األخرى (كلغة ‪ Visual Basic‬مثال) ولكن بعد أن تقحم نفسك في عالم البرمجة بلغة ‪ C#‬ستجد أن‬ ‫االسلوب الذي تستخدمه هو أسلوب محسوس ومن الممكن أن تكتب شيفرة مفهومة دون عناء شديد‪.

Tasks‬‬ ‫‪namespace Console_hello_world‬‬ ‫{‬ ‫‪class Program‬‬ ‫{‬ ‫‪.‫باإلضافة لما سبق سنجد ضمن شيفرة ‪ C#‬ما يعرف بالتعليقات وال تمثل هذه التعليقات شيفرة برمجية‬ ‫حقيقية وإنما وصفا توضيحيا ألسطر الشيفرة التي تكتبها‪.‪System.‬‬ ‫إن كتابة التعليقات ضمن الشيفرة البرمجية له الكثير من الفوائد والتي سنكتشفها مع الوقت حيث يمكننا أن‬ ‫نكتب أي نص ضمن التعليقات وبأي لغة كانت وسيتجاهل مترجم ‪ C#‬هذه التعليقات عند ترجمة الشيفرة‬ ‫حيث أن هذه التعليقات ستساعدنا على تذكر ما نقوم به ضمن الشيفرة كان تكتب مثال "يقوم هذا السطر‬ ‫بسؤال المستخدم عن اسمه" وللغة ‪ C#‬اسالي ب مختلفة في كتابة التعليقات يسمى االسلوب األول بالتعليقات‬ ‫السطرية أما االسلوب الثاني فيسمى بالتعليقات الحرة‪.‬‬ ‫لنلق نظرة على تطبيق ‪ Console‬الذي تناولناه في الفصل السابق ولنحاول تجزئة شيفرة هذا التطبيق إلى‬ ‫أجزاء محددة‪:‬‬ ‫‪using‬‬ ‫.Linq‬‬ ‫‪using‬‬ ‫.‬‬ ‫هناك نقطة أخرى يجب أن نذكرها هنا وهي أن ‪ C#‬متحسسة لحالة األحرف بعكس لغات البرمجة األخرى‬ ‫أي اننا إذا كتبنا تعليمة ما بأحرف كبيرة وهي ممثلة في االصل بأحرف صغيرة فإن ذلك سيتسبب بخطأ‬ ‫في ترجمة المشروع‪.Generic‬‬ ‫‪using‬‬ ‫.Threading.Collections.‪System.‪System‬‬ ‫‪using‬‬ ‫.Text‬‬ ‫‪using‬‬ ‫.‪System.34 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .‬‬ ‫إن الصيغة العامة للتعليقات السطرية هي كما يلي‪:‬‬ ‫يقوم هذا السطر بإظهار صندوق رسائل مكتوب عليه رسالة ترحيب ‪//‬‬ ‫أي أن التعليقات تبدأ بالرموز "‪ "//‬وبعد هذه الرموز يمكننا كتابة التعليق الذي نريد طالما أن هذا التعليق‬ ‫يقع ضمن سطر واحد وإال فإن المترجم سيعطينا رسالة خطأ ولتصحيح الخطأ يجب وضع "‪ "//‬قبل السطر‬ ‫الثاني وهكذا لكن أحيانا نحن بحاجة لكتابة عدة أسطر كتعليق فكيف ذلك إن ‪ C#‬توفر ذلك من خالل‬ ‫التعليقات الحرة وذلك بجعل التعليق بين رمزين من الشكل "*‪ "/‬كما في الشكل التالي‪:‬‬ ‫‪ */‬يقوم هذا السطر بإظهار صندوق رسائل مكتوب عليه رسالة ترحيب *‪/‬‬ ‫هناك نوع ثالث من التعليقات يسمى بتعليق التوثيق وهو يسمح بتوثيق شيفرتنا المصدرية و هو تعليق‬ ‫سطري يكون مسبوقا بالرمز "‪ "///‬وتساعدنا تعليقات التوثيق في إنشاء ملف نصي ذو تنسيق خاص أثناء‬ ‫ترجمة المشروع‪.‪System.

WriteLine("HELLO WORLD‬‬ ‫تمكين المستخدم من القراءة بعد تشغيل البرنامج ‪//‬‬ ‫.)(‪Console.)"‪Console. > ‪< Type > < name‬‬ ‫هناك بعض االمور التي يجب أن نتبعها كي نتمكن من استخدام المتغيرات بصورة سليمة ودون حدوث‬ ‫أخطاء‪:‬‬ ‫‪.‬‬ ‫نظريا ال تختلف فكرة المتغيرات في ‪ C#‬عن لغات البرمجة القديمة ولكنها تختلف اختالفا جذريا في‬ ‫بنيتها التحتية عما كانت عليه في السابق كما سترى الحقا‪.)(‪Console.‬‬ ‫إن صيغة التصريح عن المتغير في ‪ C#‬بسيطة للغاية حيث نحدد نوع المتغير أوال ثم نتبعه باسم المتغير‬ ‫كما في الشكل التالي‪:‬‬ ‫.‪Console.BackgroundColor = ConsoleColor.‬‬ ‫المتغيرات والثوابت هي عبارة عن أماكن لتخزين البيانات حيث ال يختلف مبرمجان اثنان على اهمية‬ ‫موضوع المتغيرات في أي لغة برمجة وإذا كان أساس إتقان اللغات الطبيعية هو تعلم حروف ومفردات‬ ‫تلك اللغة فان أساس إتقان لغات البرمجة هو تعلم المتغيرات والثوابت التي تبني بها إجراءات برامجك ‪.Blue‬‬ ‫لجعل لون النص أحمر ‪//‬‬ ‫.WriteLine("testing! 1.Red‬‬ ‫إلظهار نص معين على الشاشة السوداء ‪//‬‬ ‫.35 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .ForegroundColor = ConsoleColor. ‫)‪static void Main(string[] args‬‬ ‫{‬ ‫لجعل الخلفية زرقاء ‪//‬‬ ‫.‪Console.)"‪Console.Read‬‬ ‫.3‬‬ ‫.2.ReadLine‬‬ ‫}‬ ‫}‬ ‫}‬ ‫يمكنك أن تالحظ أن جميع العناصر التي ناقشناها سابقا موجودة في هذه الشيفرة يمكننا أن نجد الفواصل‬ ‫المنقوطة باإلضافة إلى االقواس }{ والتعليقات الحظ أيضا طريقة تنسيق الشيفرة وكيفية استخدام المسافة‬ ‫البادئة وفقا للكتل البرمجية‪.

‫‪ -1‬ال يمكن استخدام المتغير قبل التصريح عنه وإذا قمت بذلك فسوف يؤدي إلى حدوث خطأ في‬
‫الترجمة‪.‬‬
‫‪ -2‬ال يمكن استخدام المتغير قبل أن نسند له قيمة محددة وسيؤدي قيامك بذلك إلى حدوث خطأ في‬
‫الترجمة أيضا‪.‬‬
‫‪ -3‬أسماء المتغيرات متحسسة لحالة االحرف وهذا يعني أن المتغير ذو االسم ‪ hussam‬ليس هو‬
‫نفسه المتغير ‪.HUSSAM‬‬
‫و الجدول التالي يبين أنواع البيانات التي يمكن تعريف المتغيرات بها في ‪:C#‬‬
‫النوع‬ ‫االسم‬
‫الوصف‬ ‫الحجم‬
‫او الفئة ‪Class‬‬ ‫القصير‬
‫أرقام صحيحة‬
‫قيمة عددية صحيحة ‪0 to 255‬‬ ‫‪8‬‬ ‫‪System. Byte‬‬ ‫‪Byte‬‬
‫قيمة عددية صحيحة ‪-128 to 127‬‬ ‫‪8‬‬ ‫‪System.SByte‬‬ ‫‪SByte‬‬
‫قيمة عددية صحيحة ‪-2,147,483,648 to‬‬ ‫‪32‬‬ ‫‪System.Int32‬‬ ‫‪int‬‬
‫‪2,147,483,647‬‬
‫عددية صحيحة ‪0 to 4294967295‬‬ ‫قيمة‬ ‫‪32‬‬ ‫‪System.UInt32‬‬ ‫‪uint‬‬
‫عددية صحيحة ‪-32,768 to 32,767‬‬ ‫قيمة‬ ‫‪16‬‬ ‫‪System.Int16‬‬ ‫‪short‬‬
‫عددية صحيحة ‪0 to 65535‬‬ ‫قيمة‬ ‫‪16‬‬ ‫‪System.UInt16‬‬ ‫‪ushort‬‬
‫‪-9223372036854775808 to‬‬ ‫قيمة عددية صحيحة‬ ‫‪64‬‬ ‫‪System.Int64‬‬ ‫‪long‬‬
‫‪9223372036854775807‬‬
‫قيمة عددية صحيحة ‪0 to 18446744073709551615‬‬ ‫‪64‬‬ ‫‪System.UInt64‬‬ ‫‪ulong‬‬
‫أنواع مختلفة‬
‫التاريخ من ‪ 9991/1/1‬إلى ‪9999/12/31‬‬ ‫‪64‬‬ ‫‪System.Data‬‬ ‫‪Data‬‬
‫رمز (محرف) بنظام ‪Unicode‬‬ ‫‪16‬‬ ‫‪System.Char‬‬ ‫‪Char‬‬
‫قيمة منطقية (‪)True or False‬‬ ‫‪8‬‬ ‫‪System.Boolean‬‬ ‫‪bool‬‬
‫جميع االنواع‬ ‫‪System.Object‬‬ ‫‪Object‬‬
‫سلسلة من المحارف بنظام ‪Unicode‬‬ ‫‪System.String‬‬ ‫‪String‬‬
‫أرقام الفاصلة العائمة‬
‫قيمة عددية تقبل فاصلة عائمة ‪-3.402823e38 to‬‬ ‫‪32‬‬ ‫‪System.Single‬‬ ‫‪float‬‬
‫‪3.402823e38‬‬
‫‪-‬‬ ‫قيمة عددية تقبل فاصلة عائمة‬ ‫‪64‬‬ ‫‪System.Double‬‬ ‫‪Double‬‬
‫‪1.79769313486232e308 to‬‬
‫‪1.79769313486232e308‬‬
‫‪±1.0 × 10e−28‬‬ ‫قيمة عددية صحيحة أو تقبل فاصلة‬ ‫‪128‬‬ ‫‪System.Decimal Decimal‬‬
‫‪to ±7.9 × 10e28‬‬

‫مالحظة‪ :‬يمكن كتابة االسم القصير أو اسم النوع في شيفرة ‪ C#‬والنتيجة واحدة‪.‬‬

‫‪- 36 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬

‫ال يمكن استخدام الكلمات المحجوزة ( ‪ )keywords‬كأسماء للمتغيرات وهناك قاعدتين اساسيتين لتسمية‬
‫المتغيرات وهما‪:‬‬
‫‪ -1‬يجب أن يكون الرم ز االول من اسم المتحول حرفا هجائيا أو الرمز "_" أو الرمز "@" فقط وال‬
‫يمكن غير ذلك‪.‬‬
‫‪ -2‬يمكن للرموز االخرى الالحقة بعد الرمز االول أن تكون اي حرف هجائي أو رقم أو الرمز "_"‬
‫فقط‪.‬‬
‫باإلضافة إلى ذلك فإن هناك كلمات محجوزة لها معان خاصة بمترجم ‪ C#‬مثل الكلمة ‪ using‬والكلمة‬
‫‪ namespace‬والتي ال يجب أن نستخدمها كأسماء للمتغيرات‪.‬‬
‫وعلينا أن نتذكر أن ‪ C#‬متحسسة لحالة االحرف وبالتالي يجب أال ننسى حالة الحروف التي استخدمناها‬
‫عند التصريح عن المتغيرات وهذا يعني أن اسم المتحول الواحد المكتوب بحاالت مختلفة من حاالت‬
‫الحرف الالتيني تمثل أسماء متحوالت مختلفة عن بعضها البعض‪.‬‬

‫إن أسماء المتغيرات هي شيء سنستخدمه بكثرة عند برمجة التطبيقات وبسبب ذلك فإنه من المنطقي أن‬
‫نتحدث عن المتغيرات وأساليب تسميتها بتفصيل أكبر‪.‬‬
‫إن أكثر أساليب تسمية المتغيرات المتبعة اليوم هي قواعد تسمية ليزنسكي ( ‪Leszynski Naming‬‬
‫‪ )Conventions‬و تسمى أيضا بالتدوين الهنغاري تعتمد هذه الطريقة على وضع بادئة (‪ )Prefix‬لكل‬
‫اسم متغير يشير إلى نوع بيانات المتغير على سبيل المثال إذا كان المتغير من نوع ‪ integer‬فإننا سنضع‬
‫‪ int‬في بداية اسم المتحول أو ربما وضع الحرف ‪ i‬فقط ووضع البادئة ‪ str‬قبل اسم المتغير من النوع‬
‫‪ string‬إن استخدام هذا االسلو ب في تسمية المتغيرات مفيد جدا و لكن ليس للغة برمجة حديثة مثل لغة‬
‫‪ C#‬و السبب في ذلك يعود إلى إمكانية تعريف عدد غير محدد من االنواع في ‪ C#‬والذي سيضطرنا إلى‬
‫استخدام بادئات عديدة منها ما قد يكون عونا لنا وم نها ما قد يتسبب لنا ارباكا حقيقيا‪.‬‬
‫لقد أدرك المطورون أخيرا أن تسمية المتغيرات وفقا لمعنى البيانات المحفوظة ضمنها ولغرض هذه‬
‫المتغيرات هو أفضل أسلوب لتسمية المتغيرات أما بالنسبة لمعرفة نوع هذا المتغير فإن ‪Visual Studio‬‬
‫يوفر لنا طريقة ذكية لذلك فبمجرد أن نضع مؤشر الفارة فوق اسم المتغير سيظهر تلميح على الشاشة يبين‬
‫نوع المتغير‪.‬‬

‫‪- 37 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬

‫في الحقيقة هناك طريقتان مستخدمتان لتسمية المتغيرات في فضاءات أسماء إطار عمل ‪ .NET‬وتعرف‬
‫هاتان القاعدتين بقاعدة ‪ PascalCase‬وقاعدة ‪ camelCase‬تستخدم هاتين القاعدتين بصورة خاصة‬
‫لوصف محتوى المتحول من خالل اسمه حتى وإن تخلل هذا الوصف أكثر من كلمة واحدة إن الفارق‬
‫الرئيسي بين هاتين القاعدتين هو أن القاعدة ‪ PascalCase‬يكون الحرف االول منها كبيرا أما قاعدة‬
‫‪ camelCase‬فإن الحرف األول منها يكون صغيرا‪.‬‬
‫إليك بعض أسماء المتغيرات وفقا لقاعدة ‪:camelCase‬‬
‫‪age‬‬
‫‪firstName‬‬
‫وأسماء المتحوالت التالية وفقا لقاعدة ‪:PascalCase‬‬
‫‪Age‬‬
‫‪FirstName‬‬
‫سوف نستخدم قاعدة التسمية ‪ PascalCase‬ألغراض التسمية األكثر تقدما وقاعدة التسمية ‪camelCase‬‬
‫للمتغيرات البسيطة وهذا ما تنصح به شركة ‪.Microsoft‬‬
‫تطبيق حول التصريح عن المتغيرات والتعامل معها‪:‬‬
‫‪ -1‬قم بإنشاء تطبيق ‪ Console‬جديد باسم ‪.Console Variables‬‬
‫‪ -2‬أضف الشيفرة البرمجية التالية إلى محرر نصوص ‪.C#‬‬
‫{‬
‫التصريح عن المتغيرات‪//‬‬
‫;‪int myInteger‬‬
‫;‪string myString‬‬
‫اسناد قيم للمتغيرات ‪//‬‬
‫;‪myInteger = 17‬‬
‫;"‪myString ="\"myinteger\" is‬‬
‫إظهار القيم ‪//‬‬
‫;)‪Console.WriteLine("{0}....{1}.", myString, myInteger‬‬
‫}‬

‫‪ -3‬نفذ التطبيق بالضغط على مفتاح ‪ Ctrl+F5‬فيظهر الشكل (‪.)3-1‬‬

‫الشكل (‪)3- 1‬‬

‫‪- 38 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬

‫كيفية العمل‪:‬‬
‫‪How it Works:‬‬
‫أن الشيفرة التي أضفناها تقوم بثالثة أمور‪:‬‬
‫‪ -1‬التصريح عن متغيرين‪.‬‬
‫‪ -2‬اسناد القيم إلى هذين المتغيرين‪.‬‬
‫‪ -3‬إخراج قيم هذين المتغيرين على نافذه ‪.Console‬‬
‫حيث يصرح السطر االول عن متغير باسم ‪ myInteger‬من نوع ‪ int‬والسطر الثاني يصرح عن متغير‬
‫باسم ‪ myString‬من نوع ‪.String‬‬
‫;‪int myInteger‬‬
‫;‪string myString‬‬
‫أما السطرين التاليين فمهمتهما اسناد القيم إلى المتغيرين المصرح عنهما‪.‬‬
‫;‪myInteger = 17‬‬
‫;"‪myString ="\"myinteger\" is‬‬
‫لقد قمنا هنا بإسناد قيمتين حرفيتين ( ‪ )literal values‬للمتغيرين باستخدام عامل االسناد "=" لقد أسندنا‬
‫القيمة ‪ 17‬للمتغير ‪ myInteger‬وأسندنا النص ‪ "myinteger" is‬مع رمزي االقتباس " " للمتحول‬
‫‪ myString‬ووفقا للشيفرة السابقة نالحظ أنه كي نتمكن من إسناد أو استخدام نص أو سلسلة بشكل حرفي‬
‫في شيفرتنا البرمجية يجب أن نضع السلسة النصية ضمن عالمتي اقتباس " " هذا باإلضافة إلى أن علينا‬
‫تجنب استخدام رموز محددة مثل عالمة االقتباس نفسها ضمن النص ولكي نتمكن من استخدام هذه الرموز‬
‫يجب أن نستخدم التركيب البديل لها أو ما يسمى بتتابع الفرار(‪ )escape sequence‬وذلك باستخدام‬
‫التركيب "\ كي نتمكن من كتابة رمز عالمة االقتباس " ضمن السلسلة النصية ‪:‬‬
‫;"‪myString ="\"myinteger\" is‬‬

‫واالن إذا كتبنا السطر السابق دون استخدام التركيب البديل كما يلي‪:‬‬
‫;"‪myString =""myinteger" is‬‬

‫سيؤدي ذلك إلى حدوث خطأ في الترجمة‪.‬‬
‫هناك قواعد أخرى تتعلق باستخدام السالسل النصية بصورة حرف ية عند كتابة الشيفرة من هذه القواعد أنه‬
‫ال يمكن للسلسلة النصية أن تتجاوز سطر واحد وإذا أردنا كتابة سلسلة نصية على عدة أسطر علينا أن‬
‫نستخدم التركيب البديل لرمز فاصل السطر (‪ )line break‬وهو ‪ \n‬على سبيل المثال‪:‬‬
‫‪myString ="This string has no‬‬

‫;"‪line break‬‬

‫سيؤدي هذا السطر إلى حدوث خطأ في الترجمة وبدال من ذلك يجب كتابة‪:‬‬
‫;"‪myString ="This string has no \n line break‬‬

‫والنتيجة ستكون كما في الشكل (‪:)3-2‬‬

‫‪- 39 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬

.40 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ... myInteger‬‬ ‫هذا السطر هو إلخراج نص ما على نافذة ‪ Console‬إال أننا نجد هنا استخداما للمتغيرات ضمن هذه‬ ‫التعليمة إلخراج النصوص على نافذة ‪ Console‬نالحظ أن ما لدينا ضمن األقواس هو ما يلي‪:‬‬ ‫‪ -1‬سلسلة نصية‪.{1}.WriteLine("{0}.{1}. myInteger‬‬ ‫لقد رأينا في المثال السابق مثالين لقيم حرفية رقم صحيح وسلسلة نصية وألنواع البيانات االخرى قيم‬ ‫حرفية موافقة لها أيضا وهي موضحة بالجدول التالي تستخدم معظم القيم الحرفية لهذه األنواع الحقات‬ ‫( ‪ )suffixes‬حيث نظيف سلسلة من الرموز لنهاية القيمة الحرفية وذلك لتحديد النوع المطلوب‪.‬‬ ‫لبعض القيم الحرفية أنواع متعددة يتم تحديد نوعها بواسطة المترجم وباالعتماد على السياق الذي وردت‬ ‫ضمنه هذه القيم‪:‬‬ ‫‪.)‪Console.. myString..2‬‬ ‫بالعودة إلى شيفرتنا السابقة فإن هناك سطر أخير لم نتحدث عنه حتى اآلن وهو‪:‬‬ ‫.‬‬ ‫‪ -2‬الئحة من المتغيرات التي نود أن نضيف قيمتها لسلسلة الخرج حيث يفصل بين كل متغير وأخر‬ ‫برمز الفاصلة "‪ " .".‬إن جزء السلسلة النصية التي نود إخراجها هي "‪ "{0}. ‫الشكل (‪)3..‬ونالحظ أنها‬ ‫ال تحوي أي نص ذو معنى و كما رأينا أثناء التنفيذ فإن هذه السلسلة النصية ليست بالنص الذي‬ ‫ظهر على نافذة ‪ Console‬إن السبب في ذلك يعود إلى أن السلسلة النصية تلك تملك قالبا يمكننا‬ ‫من إضافة محتوى كل متغير إليها فكل تركيب من الشكل }‪ {i‬حيث ‪ i‬تمثل عددا صحيحا ضمن‬ ‫القالب يقابل قيمة لمتغير ضمن الئحة المتغ يرات التي تلي القالب والعدد الصحيح الموجود ضمن‬ ‫القوسين يمثل موقع المتغير من الئحة المتغيرات وعند إخراج النص على نافذة ‪ Console‬سيتم‬ ‫استبدال كل تركيب من الشكل }‪ {i‬بقيمة المتغير الموجود في الموقع ‪ i‬على الئحة المتغيرات‬ ‫ترقم سلسلة المتغيرات بدأ من الصفر و بناء على ذلك فإن المتغير ‪ myString‬يمثل المتغير رقم‬ ‫صفر من الئحة المتغيرات والمتغير ‪ myInteger‬يمثل المتغير رقم ‪ 1‬من الئحة المتغيرات أي‬ ‫أن }‪ {0‬تشير إلى المتحول ‪ myString‬و }‪ {1‬يشير إلى محتوى المتغير ‪.

ulong‬‬ ‫‪UL‬أو ‪ Ul‬أو ‪ uL‬أو‬ ‫‪100UL‬‬ ‫‪ ul‬أو ‪ lu‬أو ‪LU‬‬ ‫قيم صحيحة‬ ‫‪Ulong‬‬ ‫أو ‪ Lu‬أو ‪Iu‬‬ ‫‪1.41 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ . uint .5‬‬ ‫قيم حقيقية‬ ‫‪Double‬‬ ‫الحقة‬ ‫‪1. ‫مثال‬ ‫الالحقة‬ ‫الفئة‬ ‫نوع البيانات‬ ‫‪True‬أو ‪false‬‬ ‫يدون الحقة‬ ‫قيم منطقية‬ ‫‪Bool‬‬ ‫‪int .5F‬‬ ‫‪ F‬أو ‪f‬‬ ‫قيم حقيقية‬ ‫‪Float‬‬ ‫‪ D‬أو ‪ d‬أو بدون‬ ‫‪1. long .5M‬‬ ‫‪ M‬أو ‪m‬‬ ‫قيم حقيقية‬ ‫‪Decimel‬‬ ‫"‪ "a‬أو تركيب بديل‬ ‫بدون الحقة‬ ‫رمز(محرف)‬ ‫‪Char‬‬ ‫"‪ "Ujhbujnfjb‬و‬ ‫يمكن أن تتضمن‬ ‫بدون الحقة‬ ‫سلسلة رمزية‬ ‫‪string‬‬ ‫تراكيب بديلة‬ ‫لقد رأينا سابقا بعض التراكيب البديلة ( ‪ )escape sequences‬التي يمكننا استخدامها في القيم الحرفية‬ ‫للسالسل النصية والجدول التالي يجمع التراكيب البديلة‪:‬‬ ‫شيفرة الرمز في نظام‬ ‫الرمز الناتج (األصلي)‬ ‫التركيب البديل‬ ‫‪Unicode‬‬ ‫‪0x0027‬‬ ‫رمز اقتباس وحيد( ')‬ ‫'\‬ ‫‪0x0022‬‬ ‫رمز اقتباس مزدوج (")‬ ‫"\‬ ‫‪0x005c‬‬ ‫الشرطة المائلة (\)‬ ‫\\‬ ‫‪0x0000‬‬ ‫قيمة معدومة (‪)Null‬‬ ‫‪\0‬‬ ‫‪0x0007‬‬ ‫رمز تحذير (‪)Beep‬‬ ‫‪\a‬‬ ‫‪0x0008‬‬ ‫إلغاء للخلف (‪)Back space‬‬ ‫‪\b‬‬ ‫رمز تلقيم النموذج ( ‪Form‬‬ ‫‪0x000C‬‬ ‫‪\f‬‬ ‫‪)feed‬‬ ‫‪0x000A‬‬ ‫سطر جديد (‪)Line Break‬‬ ‫‪\n‬‬ ‫‪.‬‬ ‫‪100‬‬ ‫بدون الحقة‬ ‫قيم صحيحة‬ ‫‪ulong‬‬ ‫‪100U‬‬ ‫‪U‬أو ‪u‬‬ ‫قيم صحيحة‬ ‫‪Uint . ulong‬‬ ‫‪100L‬‬ ‫‪L‬أو ‪l‬‬ ‫قيم صحيحة‬ ‫‪Long .

)"\\‪Console.doc‬‬ ‫إن الرمز الوحيد الذي ال يمكننا وضعه بحرية أي بصورته الحرفية هوة عالمة االقتباس المزدوجة "‬ ‫تطبيق حول استخدام القيم الحرفية النصية‪:‬‬ ‫‪ -1‬قم بإنشاء تطبيق ‪ Console‬جديد باسم ‪.doc‬‬ ‫إن هذا مربك للغاية ولحسن الحظ فإن هناك ما يعرف بالسلسلة النصية الحرة (‪ )Verbatim string‬هذا‬ ‫يعني أن جميع الرموز الموجودة ضمن عالمتي االقتباس ستظهر كما في السلسلة النصية‪ ،‬حتى ولو‬ ‫تضمن على أي من الرموز المسرودة في الجدول السابق كما هي بصورتها األصلية (الحرفية) وإلنشاء‬ ‫سلسلة نصية حرة يجب أن نضع الرمز @ قبل السلسلة النصية كما يلي‪:‬‬ ‫"‪@"C:\Temp\MyDir\MyFileName.‬‬ ‫إن هذا يعني أن السلستين التاليتين متساويتان تماما‪:‬‬ ‫"‪"hussam\'s string‬‬ ‫"‪"hussam\u0027s string‬‬ ‫إن استخدام التراكيب البديلة أمر ال بأس به حتى اآلن ولكن ماذا لو صادفتنا سلسلة نصية تتضمن العديد‬ ‫من الرموز الموجودة في الجدول السابق لنأخذ على سبيل المثال السلسلة النصية التالية‪:‬‬ ‫"‪"C:\Temp\MyDir\MyFileName.Console String Literals‬‬ ‫‪ -2‬أضف الشيفرة البرمجية التالية إلى محرر نصوص ‪.C#‬‬ ‫)‪static void Main(string[] args‬‬ ‫{‬ ‫. ‫رمز اإلرجاع المركب‬ ‫‪0x000D‬‬ ‫‪\r‬‬ ‫(‪)Carriage Return‬‬ ‫رمز الجدولة األفقية‬ ‫‪0x0009‬‬ ‫‪\t‬‬ ‫( ‪)Horizontal Tab‬‬ ‫رمز الجدولة العمودية‬ ‫‪0x000B‬‬ ‫‪\v‬‬ ‫( ‪)Vertical Tab‬‬ ‫أن عمود شيفرة الرمز في نظام ‪ Unicode‬يشير إلى القيم الست عشرية (‪ )Hexadecimal‬للرمز كما‬ ‫هي موجودة في جدول رموز نظام تشفير ‪ Unicode‬ووفقا للجدول السابق يمكننا أن نستخدم شيفرة‬ ‫‪ Unicode‬الست عشرية لتمثيل التراكيب البديلة للرموز االصلية ولكي نستخدم هذه الطريقة يجب أن‬ ‫نضع التركيب "‪ " \u‬متبوعا بقيمة معينة تحدد القيمة الست عشرية لشيفرة الرمز وفقا لنظام ‪Unicode‬‬ ‫وهي الخانات األربعة التي تلي الحرف ‪ x‬في الجدول السابق‪.WriteLine("\'hello\' \"in\" my \\book‬‬ ‫‪.doc‬‬ ‫تتضمن هذه السلسلة النصية مسار واسم الملف ‪ MyFileName.42 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .doc‬لكن تتضمن هذه السلسلة النصية‬ ‫عدد من الرموز ال يمكننا استخدامها بشكل مباشر هكذا وإنما علينا تحويل تلك الرموز إلى تراكيب مكافئة‬ ‫لها نالحظ هناك الرمز "\ " في ثالثة مواضع ضمن السلسلة النصية وبالتالي فإن السلسلة النصية السابقة‬ ‫تكتب كما يلي (كي تصبح نظامية في ‪:)C#‬‬ ‫"‪"C:\\Temp\\MyDir\\MyFileName.

‪Int age‬‬ ‫ومن ثم نسند قيمة لهذا المتغير باستخدام عامل االسناد "=" كما يلي‪:‬‬ ‫.z=0‬‬ ‫‪.‬‬ ‫كما علمنا سابقا بأنه يتم التصريح عن المتغير بذكر نوع بياناته متبوعا باسم المتغير كما يلي‪:‬‬ ‫.y.)"‪Console.)3-3‬‬ ‫الشكل (‪)3.z‬‬ ‫التقن ية التالية التي سنعتاد عليها هي إسناد القيم للمتغيرات (ما تسمى بعملية التهيئة) في نفس سطر التصريح‬ ‫عنها وتتم هذه العملية كما يلي‪:‬‬ ‫.)"‪Console.‪Int x=20.‪Int x. ‫.‪age=25‬‬ ‫هناك بعض االمور علينا أن نعتاد عليها أثناء البرمجة بلغة ‪ C#‬أوال التصريح عن عدة متغيرات من نفس‬ ‫النوع و الذي يمكننا القيام به ضمن سطر تصريح واحد بدال من التصريح عن متغيرين أو أكثر في عدة‬ ‫أسطر حيث س يفصل بين كل متغير وأخر الرمز "‪ " .3‬‬ ‫كيفية العمل‪:‬‬ ‫‪How it Works:‬‬ ‫األمور واضحة تماما سأترك لك التعليق‪.43 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .y=33.‬كما في المثال التالي‪:‬‬ ‫.WriteLine("\0hello\0\tin\t my \vbook\v‬‬ ‫.WriteLine("\ahello in\f my bb\book\a\nhello in my book‬‬ ‫}‬ ‫‪ -3‬نفذ التطبيق بالضغط على مفتاح ‪ Ctrl+F5‬فيظهر الشكل (‪.

var3‬إلى‬ ‫‪var1=var2+var3‬‬ ‫ثنائي‬ ‫‪+‬‬ ‫متغير ‪var1‬‬ ‫اسناد حاصل طرح قيمة متغيرين (‪ )var2 .‬‬ ‫تندرج معظم العوامل تحت فئة العوامل ثنائية الحد وهناك القليل من العوامل أحادية الحد وليس في ‪C#‬‬ ‫سوى عامل ثالثي الحد وحيد يسمى بالعامل الشرطي‪.var3‬إلى‬ ‫‪var1=var2*var3‬‬ ‫ثنائي‬ ‫*‬ ‫متغير ‪var1‬‬ ‫اسناد حاصل قسمة المتغير ‪ var2‬على ‪ var3‬إلى متغير‬ ‫‪var1=var2/var3‬‬ ‫ثنائي‬ ‫‪/‬‬ ‫‪var1‬‬ ‫اسناد حاصل باقي قسمة المتغير ‪ var2‬على ‪ var3‬إلى‬ ‫ثنائي ‪var1=var2%var3‬‬ ‫‪%‬‬ ‫متغير ‪var1‬‬ ‫‪.var3‬إلى‬ ‫‪var1=var2-var3‬‬ ‫ثنائي‬ ‫‪-‬‬ ‫متغير ‪var1‬‬ ‫اسناد حاصل ضرب قيمة متغيرين (‪ )var2 .‬‬ ‫الناتج‬ ‫مثال‬ ‫العامل الفئة‬ ‫اسناد حاصل جمع قيمة متغيرين (‪ )var2 .‬‬ ‫‪ -2‬العوامل الثنائية (‪ )binary‬والتي تعالج حدين‪.‬‬ ‫يمكننا تصنيف العوامل ضمن ثالث فئات‪:‬‬ ‫‪ -1‬العوامل االحادية (‪ )unary‬والتي تعالج حدا واحدا فقط‪.‬‬ ‫‪ -3‬العوامل الثالثية (‪ )ternary‬والتي تعالج ثالثة حدود‪.‫تتضمن لغة ‪ C#‬عددا من العوامل ( ‪ )operators‬التي تستخدم بغرض معالجة المتغيرات ومن بين هذه‬ ‫العوامل عامل اال سناد "=" الذي استخدمناه مسبقا نطلق على كل تشكيلة من هذه العوامل والمتغيرات‬ ‫والقيم الحرفية بالتعبير (‪ )expression‬والذي يمثل الكتلة االساسية لعمليات الحساب في البرمجة‪.‬‬ ‫تتدرج العوامل المستخدمة في ‪ C#‬من العوامل ال بسيطة إلى العوامل المعقدة جدا والتي يمكن أن تتعرض‬ ‫لها في التطبيقات الرياضية تتضمن العوامل البسيطة جمي ع العمليات الرياضية متل الجمع والضرب‬ ‫والطرح و القسمة وصوال إلى العوامل المعقدة التي تتضمن معالجة محتوى المتغيرات عبر التمثيل البياني‬ ‫لقيمها هناك أيضا عوامل منطقية مخصصة للتعامل مع القيم المنطقية (البوليانية) باإلضافة إلى عوامل‬ ‫االسناد مثل العامل "=" سوف نركز في هذا الفصل على العوامل الرياضية وعوامل االسناد وسنترك‬ ‫العوامل المنطقية للفصل التالي حيث سنتناول المنطق البولياني في سياق حديثنا عن التحكم في تدفق‬ ‫البرنامج‪.44 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .‬‬ ‫هناك خمس عوامل رياضية بسيطة اثنان منها يمكن أن يستخدم كعوامل ثنائية أو أحادية الجدول التالي‬ ‫يسرد العوامل الثنائية مع عرض مثال سريع الستخدامها ونتائج هذه العوامل عند تطبيقها على متحوالت‬ ‫من أنواع رقمية بسيطة‪.

‫وكما قلنا فإن لبعض هذه العوامل هيئة أحادية وهي مسرودة بالجدول التالي‪:‬‬ ‫الناتج‬ ‫مثال‬ ‫الفئة‬ ‫العامل‬ ‫جمع قيمة المتغير ‪ var2‬إلى المتغير ‪var1‬‬ ‫‪var1=+var2‬‬ ‫أحادي‬ ‫‪+‬‬ ‫واسناد القيمة إلى ‪var1‬‬ ‫طرح قيمة المتغير ‪ var2‬من المتغير ‪var1‬‬ ‫‪var1=-var2‬‬ ‫أحادي‬ ‫‪-‬‬ ‫واسناد القيمة إلى ‪var1‬‬ ‫من الواضح أن استخدام هذه العوامل مع المتغيرات ذات البيانات الرقمية منطقي جدا فجميع هذه العوامل‬ ‫تمثل عمليات رياضية أساسية يمكن تطبيقها على أي نوع من أنواع البيانات العددية لكن استخدام هذه‬ ‫العوامل مع متغيرات من أنواع مختلفة كالمتغيرات المنطقية أو النصية مبهم والنتائج المتوقعة غير‬ ‫واضحة‬ ‫فما الذي تتوقعه عندما نقوم بجمع قيمتين منطقيتين مثال‪:‬‬ ‫في الحقيقة ال يمك ننا استخدام العوامل الرياضية لجمع المتغيرات المنطقية واستخدامها يؤدي إلى حصول‬ ‫خطأ في الترجمة‪.‬‬ ‫إن األمر مربك أيضا بالنسبة للمتغيرات الرمزية من نوع (‪ )char‬فهذه المتحوالت تتضمن رمزا واحدا‬ ‫فقط لكن يتم االحتفاظ بهذا الرمز على هيئة رقم صحيح يمثل شيفرة هذا الرقم في نظام تشفير ‪Unicode‬‬ ‫وبالتالي إذا حاولنا جمع متحولين رمزيين فإن النتيجة هي رمز تمث ل شيفرته حاصل جمع شيفرة المتحول‬ ‫االول مع المتحول الثاني إن هذا مثال للتحول المطلق (‪ )implicit conversion‬وسوف نتحدث عن هذا‬ ‫الموضوع بتفصيل أكبر الحقا كما أن هناك التحويل الصريح (‪ )explicit conversion‬و هو ما يحصل‬ ‫في التعابير التي تتضمن متحوالت(متغيرات) من أنواع مختلفة‪.‬‬ ‫هناك عامالن أخران مهمان جدا وهما عامل الزيادة والنقصان هذان العامالن أحاديان ويمكن استخدامهما‬ ‫بطريقتين إما بوضع العامل ب عد الحد مباشرة أو قبله مباشرة والجدول التالي يوضح كيفية استخدام هذا‬ ‫العامل‪:‬‬ ‫النتائج‬ ‫مثال‬ ‫العامل الفئة‬ ‫اسناد القيمة ‪ var2+1‬إلى المتحول ‪var1‬‬ ‫‪var1=++var2‬‬ ‫‪ ++‬أحادي‬ ‫اسناد القيمة ‪ var2-1‬إلى المتحول ‪var1‬‬ ‫‪var1=--var2‬‬ ‫أحادي‬ ‫‪--‬‬ ‫اسناد القيمة ‪ var2‬إلى المتحول ‪ var1‬ثم زيادة قيمة‬ ‫‪var1=var2++‬‬ ‫أحادي‬ ‫‪++‬‬ ‫المتحول ‪ var2‬بمقدار ‪1‬‬ ‫‪.45 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .‬‬ ‫لكن بالنسبة للمتغيرات النصية من نوع ‪ string‬فإن استخدام عامل الجمع (‪ )+‬منطقي جدا‪:‬‬ ‫النتائج‬ ‫مثال‬ ‫الفئة‬ ‫العامل‬ ‫سيحوي المتحول ‪ var1‬على السلسلة النصية للمتحول‬ ‫‪var1=var2+var3‬‬ ‫ثنائي‬ ‫‪+‬‬ ‫‪ var2‬و السلسلة النصية للمتحول ‪var3‬‬ ‫وليست هناك أية عوامل رياضية أخرى (عدا العامل ‪ )+‬يمكن استخدامها مع المتغيرات النصية‪.

)(‪Console.++var3={1}".ReadLine‬‬ ‫. ++var3‬‬ ‫. var1‬‬ ‫}‬ ‫‪ -3‬نفذ التطبيق بالضغط على مفتاح ‪ Ctrl+F5‬فيظهر الشكل (‪.WriteLine("var2++={0}.46 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .5‬‬ ‫كيفية العمل‪:‬‬ ‫‪.‪int var1. var2++. var3=6‬‬ ‫. var2=5.) ‪Console.‪var1 = var2++ * ++var3‬‬ ‫.Console Mathematical Operators‬‬ ‫‪ -2‬أضف الشيفرة البرمجية التالية إلى محرر نصوص ‪.)3-5‬‬ ‫الشكل (‪)3.4‬‬ ‫‪ -4‬قم بالضغط على زر ‪ Enter‬سيظهر لك الشكل (‪.C#‬‬ ‫)‪static void Main(string[] args‬‬ ‫{‬ ‫.)3.WriteLine(" var1={0}".)‪Console. ‫اسناد القيمة ‪ var2‬إلى المتحول ‪ var1‬ثم أنقاص قيمة‬ ‫‪var1=var2--‬‬ ‫أحادي‬ ‫‪--‬‬ ‫المتحول ‪ var2‬بمقدار ‪1‬‬ ‫إن الفكرة من هذين العاملين هي أن هناك دائما تغير في قيمة الحد فالعامل ‪ ++‬سيؤدي دائما إلى زيادة‬ ‫الحد بمقدار ‪ 1‬والعامل – سيؤدي دائما إلى إنقاص الحد بمقدار ‪ 1‬إن قيمة المتغير ‪ var1‬هنا متعلقة بأمرين‬ ‫اثنين‪:‬‬ ‫‪ -1‬قيمة المتحول ‪var2‬‬ ‫‪ -2‬موقع العامل بالنسبة للمتغير ‪ var2‬فوضع العامل قبل الحد مباشرة يعني أن الحد سيتأثر قبل أي‬ ‫عمليات حسابية متضمنة في التعبير ووضعه بعد الحد مباشرة يعني أن الحد سيتأثر بعد اتمام‬ ‫جميع العمليات الحسابية في التعبير وهذا مهم جدا‪.4‬‬ ‫الشكل (‪)3.‬‬ ‫تطبيق حول العوامل الرياضية‪:‬‬ ‫‪ -1‬قم بإنشاء تطبيق ‪ Console‬جديد باسم ‪.

)var1‬‬ ‫‪-4‬‬ ‫في السطر الخامس تم إظهار قيمة (‪ )var1‬على شاشة ‪Console‬‬ ‫‪-5‬‬ ‫لكن كيف حدث ذلك أن الحد (‪ )var2++‬يعمل عمل عداد تصاعدي ((‪ )var2--‬هو عداد تنازلي) قيمته‬ ‫االولى هي االسناد الذي حددناه وهو الرقم خمسة فقيمته في االظهار األول كانت تساوي (‪ )5‬أما في‬ ‫االظهار الثاني تساوي(‪.C#‬‬ ‫)‪static void Main(string[] args‬‬ ‫{‬ ‫.ReadLine‬‬ ‫. firstNumber.ReadLine‬‬ ‫‪Console.))(‪secondNumber = Convert.)"‪Console.‬‬ ‫. userName‬‬ ‫.‫‪How it Works:‬‬ ‫إن الشيفرة التي أضفناها قامت بما يلي‪:‬‬ ‫في السطر االول التصريح عن ثالث متغيرات من النوع ‪ int‬األول لم نقم بإسناد له قيمة مباشرة‬ ‫‪-1‬‬ ‫أما االخرين قمنا بإسناد قيم مباشرة لهما‪.47 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .WriteLine("enter your name:‬‬ ‫.))(‪firstNumber = Convert.WriteLine("welcom {0}!".)(‪userName = Console.)6‬‬ ‫أما الحد (‪ )++var3‬فهو يعمل عمل عداد تصاعدي ((‪ )--var2‬هو عداد تنازلي) أيضا إال أن الفرق عن‬ ‫العداد السابق هو أن قيمته األولى تزيد بمقدار (‪ )1‬فكانت قيمة إظهاره االول تساوي (‪ )7‬وفي االظهار‬ ‫الثاني تساوي (‪)8‬‬ ‫مالحظة‪ :‬ال يمكننا استخدام القيم الحرفية مع العاملين ‪ ++‬و – وهذا يعني أن التعبير التالي خاطئ‪:‬‬ ‫‪Var1=++6‬‬ ‫وسيؤدي إلى حدوث خطأ في الترجمة ولكي نحقق عملية كهذه يجب أن نضع القيمة الحرفية ضمن متغير‬ ‫كما فعلنا سابقا‪.".‬‬ ‫‪.WriteLine("now give a number:‬‬ ‫.‪Double firstNumber.enter‬‬ ‫‪-3‬‬ ‫في السطر الرابع تم اسناد قيمة للمتحول (‪.ReadLine‬‬ ‫.‬‬ ‫تطبيق أخر حول معالجة المتغيرات بالعوامل الرياضية‪:‬‬ ‫‪ -1‬قم بإنشاء تطبيق ‪ Console‬جديد باسم ‪.)‪Console. ++var3‬‬ ‫في السطر الثالث تم اسناد أمر تمكين القراءة واالنتقال لألمر التالي بعد الضغط على زر ‪.)"‪Console.ToDouble(Console.‪string userName‬‬ ‫.)"‪Console.ToDouble(Console.".Console process variables‬‬ ‫‪ -2‬أضف الشيفرة البرمجية التالية إلى محرر نصوص ‪. firstNumber + secondNumber‬‬ ‫‪Console.)‪secondNumber.WriteLine("the sum {0}and{1}is{2}.WriteLine("now give me anather number:‬‬ ‫. secondNumber‬‬ ‫.WriteLine("the result subtracting{0}from{1}is{2}.‬‬ ‫في السطر الثاني قمنا بإظهار قيم التحوالت على نافذة ‪ Console‬بعد أن طبقنا عليها بعض‬ ‫‪-2‬‬ ‫العوامل الرياضية (‪)var2++.

". firstNumber. Console. Console.".7( ‫الشكل‬ )3-8( ‫ الشكل‬Enter ‫ ثم أدخل رقما أخر ثم اضغط‬Enter ‫ أدخل رقما ثم أضغط‬-5 )3-8( ‫الشكل‬ :‫كيفية العمل‬ How it Works: . secondNumber. firstNumber .WriteLine("the rrmainder of dividing {0} by {1} is {2}. firstNumber.WriteLine("the product of {0} and {1} is {2}. secondNumber.". firstNumber / secondNumber). firstNumber % secondNumber). ‫ املهندس حسام الدين الرز‬:‫إعداد‬ . secondNumber. Console. firstNumber.WriteLine("the result dividing {0} by {1} is {2}.)3-6( ‫ فيظهر الشكل‬Ctrl+F5 ‫ نفذ التطبيق بالضغط على مفتاح‬-3 )3.6( ‫الشكل‬ . firstNumber * secondNumber). { .)3-7( ‫ الشكل‬Enter ‫ أدخل اسمك ثم اضغط‬-4 )3.48 . secondNumber. firstNumber.secondNumber).

‫باإلضافة للعوامل الرياضية فإن هذه الشيفرة تستعرض مفهومين مهمين سنستعرض لهما في العديد من‬
‫األمثلة الالحقة‪:‬‬
‫‪ -1‬دخل المستخدم‪.‬‬
‫‪ -2‬تحويل النوع‪.‬‬
‫يظهر أمر الحصول على دخل المستخدم (وهو ‪ )Console.Readline‬مشابه لصيغة األمر‬
‫)(‪ Console.WriteLine‬المستخدم إلخراج النصوص على نافذة ‪ Console‬يقوم هذا األمر بحث‬
‫المستخدم على دخل ما و هو ما سيخزن ضمن متحول من نوع ‪: string‬‬
‫;‪string userName‬‬
‫;)"‪Console.WriteLine("enter your name:‬‬
‫;)(‪userName = Console.ReadLine‬‬
‫;)‪Console.WriteLine("welcom {0}!", userName‬‬
‫تقوم هذه الشيفرة بكتابة محتوى المتحول ‪ userName‬على نافذة الخرج‪.‬‬
‫لقد قمنا بقراءة عددين في هذا المثال حيث استخدمنا االمر )(‪ Console.ReadLine‬مرتين للحصول‬
‫على دخل من المستخدم والذي يمثل هذين العدد ين لقد ذكرنا أن القيمة الناتجة من االمر‬
‫)(‪ Console.ReadLine‬هي سلسلة نصية من نوع ‪ String‬تمثل الدخل الذي تم إدخاله على نافذة‬
‫‪ Console‬أي أن أي نوع من البيانات نقوم بإدخاله ال يمثل إال نصا وحتى إن كان الدخل عبارة عن أرقام‬
‫فقط ولهذا السبب توجب علينا استخدام مفهوم تحويل نوع البيانات (‪ )Type Conversion‬وسوف نتناول‬
‫موضوع تحويل االنواع الحقا‬
‫لنعد إلى شيفرة التطبيق من البداية أوال قمن بالتصريح عن متحولين رقميين من نوع ‪: Double‬‬
‫;‪Double firstNumber, secondNumber‬‬

‫بعد ذلك طلبنا من المستخدم إدخال العدد األول ثم أستخدمنا األمر ‪ Convert.ToDouble‬على سلسلة‬
‫الدخل الناتجة من األمر )(‪ Console.ReadLine‬وذلك لتحويل السلسلة النصية ذات النوع ‪ String‬إلى‬
‫بيانات رقمية من نوع ‪ Double‬بعد ذلك قمنا بإسناد القيمة الناتجة إلى المتحول ‪:firstNumber‬‬
‫;)"‪Console.WriteLine("now give a number:‬‬
‫;))(‪firstNumber = Convert.ToDouble(Console.ReadLine‬‬
‫إن عملية التحويل تلك بسيطة للغاية وستجد الحقا أن العديد من عمليات التحويل األخرى تؤدي بنفس‬
‫الطريقة والسهولة واالمر مشابه أيضا للحصول على العدد التالي‪:‬‬
‫;)"‪Console.WriteLine("now give me anather number:‬‬
‫;))(‪secondNumber = Convert.ToDouble(Console.ReadLine‬‬

‫بعد ذلك سنطبع ناتج جمع وطرح وضرب وقسمة وباقي قسمة هذين العددين على نافذة الخرج‪:‬‬
‫‪Console.WriteLine("the sum {0}and{1}is{2}.", firstNumber,‬‬
‫;)‪secondNumber, firstNumber + secondNumber‬‬
‫‪Console.WriteLine("the result subtracting{0}from{1}is{2}.",‬‬
‫;)‪firstNumber, secondNumber, firstNumber - secondNumber‬‬
‫‪Console.WriteLine("the product of {0} and {1} is {2}.",‬‬
‫;)‪firstNumber, secondNumber, firstNumber * secondNumber‬‬
‫‪Console.WriteLine("the result dividing {0} by {1} is {2}.",‬‬

‫‪- 49 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬

‫;)‪firstNumber, secondNumber, firstNumber / secondNumber‬‬
‫‪Console.WriteLine("the rrmainder of dividing {0} by {1} is {2}.",‬‬
‫;)‪firstNumber, secondNumber, firstNumber % secondNumber‬‬

‫الحظ أننا استخدمنا التعبير ‪ firstNumber + secondNumber‬كبارامتر لألمر‬
‫)(‪ Console.WriteLine‬أي أننا لم نخزن ناتج الجمع ضمن متحول واستخدمنا هذا المتحول إلخراج‬
‫قيمة الجمع‪:‬‬
‫‪Console.WriteLine("the sum {0}and{1}is{2}.", firstNumber,‬‬
‫;)‪secondNumber, firstNumber + secondNumber‬‬
‫إن هذا النوع من الصيغ يجعل شيفرتنا البرمجية مقروءة ويزيل كمية األسطر البرمجية الزائدة التي قد‬
‫تحتاج لكتابتها‪.‬‬

‫لم نستخدم حتى االن سوى عامل اسناد بسيط وهو (=) إال أن هناك العديد من عوامل االسناد االخرى‬
‫المفيدة جدا في الكثير من الحاالت‪.‬‬
‫إن جميع عوامل االسناد عدا العامل "=" تعمل بصورة مشابهة كما أن لجميع عوامل االسناد مبدأ واحدا‬
‫وهو أن قيمة المتحول على يمين العامل ستسند إلى المتحول على يساره‪.‬‬
‫الجدول التالي يبين عوامل االسناد باإلضافة إلى طريقة استخدامها‪:‬‬
‫الناتج‬ ‫مثال‬ ‫العامل الفئة‬
‫اسناد قيمة ‪ var2‬إلى ‪var1‬‬ ‫‪Var1=var2‬‬ ‫ثنائي‬ ‫=‬
‫اسناد حاصل جمع ‪ var1‬مع ‪ var2‬إلى المتغير ‪var1‬‬ ‫‪Var1+=var2‬‬ ‫=‪ +‬ثنائي‬
‫اسناد حاصل طرح ‪ var2‬من ‪ var1‬إلى المتغير ‪var1‬‬ ‫‪Var1-=var2‬‬ ‫=‪ -‬ثنائي‬
‫اسناد حاصل ضرب ‪ var1‬مع ‪ var2‬إلى المتغير ‪var1‬‬ ‫‪Var1*=var2‬‬ ‫=* ثنائي‬
‫اسناد حاصل قسمة ‪ var1‬على ‪ var2‬إلى المتغير ‪var1‬‬ ‫‪Var1/=var2‬‬ ‫=‪ /‬ثنائي‬
‫اسناد حاصل باقي فسمة ‪ var1‬على ‪ var2‬إلى المتغير ‪var1‬‬ ‫‪Var1%=var2‬‬ ‫=‪ %‬ثنائي‬

‫وكما ترى فإن هذه العوامل ال تمثل إال اختصارا للتعابير التي تستخدم عامل االسناد الطبيعي "=" مع‬
‫أحد العوامل الرياضية التي تعرفنا عليها منذ قليل فالتعبير التالي‪:‬‬
‫‪var1=var1+var2‬‬
‫مكافئ تماما للتعبير‪:‬‬
‫‪var1+=var2‬‬
‫وقس على ذلك على باقي عوامل االسناد االخرى الموجودة في الجدول‪.‬‬

‫‪- 50 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬

‫مالحظ إن العامل (=‪ )+‬هو الوحيد الذي يمكن استخدامه مع المتغيرات النصية من نوع ‪ String‬أما باقي‬
‫العوامل فال يمكن استخدامها إال مع المتغيرات الرقمية فقط والمتحوالت الرمزية من نوع ‪.char‬‬

‫عند تنفيذ تعبير ما فإن كل عامل سيطبق على حدوده وفق تتابع محدد وهذا ال يعني بالضرورة معالجة‬
‫العوامل من اليسار إلى اليمين‪.‬‬
‫بالعودة إلى مثال سابق لنأخذ الشيفرة التالية‪:‬‬
‫;‪var1=var2+var3‬‬
‫هنا سيعالج العامل (‪ )+‬قبل العامل (=)‪.‬‬
‫هناك أوضاع أخرى تتجلى فيها أسبقية بعض العوامل على غيرها كما في المثال التالي‪:‬‬
‫;‪var1=var2+var3*var4‬‬
‫ه نا سيعالج العامل (*) أوال ثم العامل (‪ )+‬ومن ثم العامل (=) الحظ أن هذا هو الترتيب الرياضي الطبيعي‬
‫للحساب والنتيجة التي سنحصل عليها مطابقة تماما لما يمكن أن نحصل عليه عند احتساب تعبير كهذا‬
‫بالورقة والقلم‪.‬‬
‫وكما في الرياضيات فإنه يمكننا التحكم في أسبقية العوام ل باستخدام األقواس على سبيل المثال‪:‬‬
‫;‪var1= (var2+var3)*var4‬‬
‫هنا ستتم أوال تنفيذ العامل (‪ )+‬ومن ثم سيعالج العامل (*) ومن ثم العامل (=)‪.‬‬
‫الجدول التالي يبين أسبقية العوامل التي تناولناها حتى االن حيث العوامل الموجودة في سطر واحد مثل‬
‫(*و‪ )/‬ستنفذ وفقا اليسار إلى اليمين‪:‬‬
‫‪ -- , ++ -1‬كبادئات ‪( - ,+ ,‬األحادية)‪.‬‬ ‫األسبقية األعلى‬
‫‪.% , / , * -2‬‬
‫‪.- , + -3‬‬
‫‪. -= , += , %= , /= , *= , = -4‬‬
‫‪ -- , ++‬كلواحق‪.‬‬ ‫األسبقية االدنى‬

‫تذكر ان استخدام االقواس سيلغي هذا الترتيب‪.‬‬
‫وبناء على ذلك نخلص للخالصة التالية بما يخص أسبقية العوامل الرياضية حيث سيتعامل معها منا يلي‪:‬‬

‫‪- 51 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬

‫‪ -1‬ما بداخل األقواس أوال وإذا كانت األقواس متداخلة فتبدأ العملية من أقصى قوس في الداخل بمعنى‬
‫لو أراد المبرمج إتمام عملية حسابية األول (حتى لو كان الطرح مع أنه أخر عملية تتم) يضعها‬
‫داخل األقواس يتم تنفيذها أول شيء‪.‬‬
‫‪( -2‬الضرب – القسمة – باقي القسمة) لهم نفس الترتيب بمعنى لو وجدت األقواس في العملية‬
‫الرياض ية يتم حساب ما باألقواس األول وإذا وجدت إحدى العمليات الثالثة السابقة (واحدة منهم‬
‫فقط) يتم تنفيذها بعد األقواس إن وجدوا الثالثة أو أثنين منهم تتم العملية الحسابية من اليسار إلى‬
‫اليمين بمعنى اللي موجود األول من ناحية اليسار يتم حسابه األول كما بالشكل التالي‪.‬‬
‫‪ -3‬الجمع‪.‬‬
‫‪ -4‬الطرح‪.‬‬
‫واألشكال توضح أسبقية العوامل الرياضية‪:‬‬

‫تمثل فضاءات االسماء ( ‪ )namespaces‬االسلوب الذي يتبعه إطار عمل ‪ .NET‬لتوفير حاويات لشيفرة‬
‫التطبيق وتستخدم فضاءات األسماء أيضا ألهداف تصنيف العناصر في إطار عمل ‪ .NET‬إن معظم هذه‬
‫العناصر عبارة عن تعاريف ألنواع البيانات مثل االنواع البسيطة المشروحة في هذا الفصل‪.‬‬
‫إن شيفرة ‪ C#‬موجودة بصورة افتراضية ضمن فضاء االسماء الشامل ( ‪ )Global namespaces‬هذا‬
‫يعني أن العناصر الموجودة ضمن هذه الشيفرة يمكن الوصول إليها من خالل شيفرة أخرى موجودة في‬
‫فضاء االسماء الشامل بمجرد االشارة إليها باالسم فقط ومع ذلك يمكننا استخدام الكلمة المحجوزة‬
‫‪ namespace‬لتعريف فضاء أسماء بصورة صريحة وذلك لكتلة معينة من الشيفرة حيث ستتوضع هذه‬
‫الشيفرة ضمن قوسي كتلة "}{" و بناء على ذلك يجب ذكر اسم فضاء االسماء الذي تنتمي له كتلة الشيفرة‬
‫كي نتمكن من استخدام العناصر الموجودة ضمن هذه الكتلة خارج فضاء األسماء هذا‪.‬‬
‫إن اسم فضاء االسماء يمثل اسما وصفيا محددا يتضمن تحته كافة المعلومات الهرمية لكتلة الشيفرة التي‬
‫يحتويها هذا يعني أنه إذا كان لدينا شيفرة في فضاء أسماء تحتاج الستخدام اسم معرف في فضاء أسماء‬
‫أخر فإن علينا تضمين مرجع لفضاء االسماء األول تستخدم االسماء المحددة ( ‪)Qualified Names‬‬
‫النقطة "‪ ".‬بين مستويات االسماء الهرمية‪.‬‬
‫لنأخذ الشيفرة التالية على سبيل المثال‪:‬‬

‫‪- 52 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬

NameOne‬‬ ‫عندما نود استخدام االسم ‪ NameOne‬ضمن فضاء االسماء ‪ LevelOne‬فإننا سنستخدمه كما هو (أي‬ ‫‪ )NameOne‬دون الحاجة لذكر فضاء االسماء الذي ينتمي له‪.)NameOne‬‬ ‫‪LevelOne .53 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .LevelTow.‫‪namespace LevelOne‬‬ ‫{‬ ‫‪//code in LevelOne namespace‬‬ ‫‪//name "NameOne" defined‬‬ ‫}‬ ‫‪//code in Global namespace‬‬ ‫تعرف هذه الشيفرة فضاء أسماء باسم ‪ LevelOne‬وكذلك تعريف اسم ضمن فضاء االسماء هذا وهو‬ ‫‪ NameOne‬الحظ أننا لم نقم فعليا بتعريف االسم لكي يكون حديثنا موجها بصورة عامة وسنفترض هنا‬ ‫أن هناك شيفرة لتعريف االسم ‪.‬‬ ‫أما بالنسبة للشيفرة الموجودة ضمن فضاء االسماء الشامل فإن علينا هنا أن نشير إلى فضاء االسماء‬ ‫‪ LevelOne‬ثم االسم ‪ NameOne‬بالصورة التالية (وهو يمثل االسم المحدد لالسم ‪. NameTow‬‬ ‫وإذا كنا ضمن فضاء االسماء ‪ LevelTow‬عندئذ يكفي أن نشير إلى االسم فقط كما يلي‪:‬‬ ‫‪. Name Tow‬‬ ‫وإذا كنا ضمن فضاء االسماء ‪ LevelOne‬عندئذ يجب أن نشير إلى االسم وفقا لما يلي‪:‬‬ ‫‪LevelTow.‬بين كل مستوى من مستويات فضاءات االسماء لنأخذ فضاءات‬ ‫االسماء التالية‪:‬‬ ‫‪namespace LevelOne‬‬ ‫{‬ ‫‪//code in LevelOne namespace‬‬ ‫‪namespace LevelTow‬‬ ‫{‬ ‫‪//code in LevelOne. NameOne‬‬ ‫يمكننا تعشيش فضاءات االسماء ضمن بعضها البعض وذلك باستخدام الكلمة المحجوزة ‪namespace‬‬ ‫أيضا ولكي نتمكن من الوصول إلى عناصر كل فضاء أسماء علينا ذكر تسمية فضاءا ت وفقا لهرمية‬ ‫التعشيش وذلك بوضع رمز النقطة "‪ ". LevelTow namespace‬‬ ‫‪// name "NameTow" defined‬‬ ‫}‬ ‫}‬ ‫‪//code in Global namespace‬‬ ‫وهنا بفرض أننا نود الوصول إلى االسم ‪ NameTow‬من ضمن فضاء االسماء الشامل عندئذ يجب أن‬ ‫نشير إلى االسم وفقا لما يلي‪:‬‬ ‫‪LevelOne .

LevelTow‬دون ذكر االسم المحدد كامال‪:‬‬ ‫‪namespace LevelOne‬‬ ‫{‬ ‫.‬‬ ‫بالعودة إلى الشيفرة السابقة نالحظ أننا كي نتمكن من الوصول إلى االسماء الموجودة ضمن فضاء االسماء‬ ‫‪ LevelTow‬من ضمن فضاء االسماء الشامل علينا أن نشير إلى اسم فضاء االسماء ‪ LevelOne‬ثم اسم‬ ‫فضاء االسماء ‪ LevelTow‬ومن ثم االسم المعرف ضمن فضاء االسماء ‪ LevelTow‬على الرغم من‬ ‫أن هذا منطقي جدا إال انه مربك في كثير من االحيان (تصور أن يكون لدينا أربعة أو خمسة مستويات‬ ‫من ت عشيش فضاءات االسماء تخيل كيف ستشير إلى اسم معرف ضمن فضاء االسماء في المستوى‬ ‫الخامس!) لهذا السبب وجدت في ‪ C#‬الكلمة المفتاحية ‪ using‬بواسطة هذه الكلمة لن يطلب منك المترجم‬ ‫ذكر االسم المحدد كامال على سبيل المثال لقد ذكرنا في الشيفرة السابقة أن الشيفرة الموجودة ضمن فضاء‬ ‫االسماء ‪ LevelOne‬يجب أن تتمكن من الوصول إلى االسماء الموجودة ضمن فضاء االسماء‬ ‫‪ LevelOne.NameThree‬و ‪ LevelOne. NameTow‬‬ ‫بمجرد ذكر ‪ NameTow‬فقط‪.‫‪NameTow‬‬ ‫النقطة الهامة التي يجب أن نشير إليها هنا هو أن االسماء يجب أن تكون فريدة ضمن فضاء االسماء‬ ‫التابعة له فال يمكننا تعريف االسم ‪ NameThree‬مرتين ضم ن فضاء االسماء الواحد ولكن يمكننا تعريف‬ ‫االسم ‪ NameThree‬ضمن فضاء األسماء ‪ LevelTow‬وتعريف اسم ‪ NameThree‬ضمن فضاء‬ ‫األسماء ‪ LevelOne‬أيضا‪:‬‬ ‫‪namespace LevelOne‬‬ ‫{‬ ‫‪// name "NameThree" defined‬‬ ‫‪namespace LevelTow‬‬ ‫{‬ ‫‪// name "NameThree" defined‬‬ ‫}‬ ‫}‬ ‫‪//code in Global namespace‬‬ ‫الحظ أن االسمين ‪ LevelOne.‬‬ ‫في بعض الحاالت قد يسبب ذلك بعض االرباك خصوصا إذا كان لدينا أسماء متشابهة في فضائي أسماء‬ ‫مختلفين (كاالسم ‪ NameThree‬في المثال السابق) إن استخدام الكلمة المحجوزة ‪ using‬في حالة كهذه‬ ‫‪.54 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .NameThree‬يمثالن‬ ‫اسمين منفصلين وسيستخدمان بصورة مستقلة عن بعضهما البعض‪.‪Using LevelTow‬‬ ‫‪namespace LevelTow‬‬ ‫{‬ ‫‪// name "NameTow" defined‬‬ ‫}‬ ‫}‬ ‫‪//code in Global namespace‬‬ ‫واالن يمكن للشيفرة ضمن فضاء االسماء ‪ LevelOne‬الوصول إلى االسم ‪LevelTow. LevelTow.

‫سيقود إلى مشاكل تضارب بين االسمين عندئذ يمكننا توفير اسم مستعار ( ‪ )alias‬لفضاء األسماء كجزء‬ ‫من التعليمة ‪:using‬‬ ‫‪namespace LevelOne‬‬ ‫{‬ ‫..Tasks‬‬ ‫‪namespace Console_process_variables‬‬ ‫{‬ ‫‪class Program‬‬ ‫{‬ ‫)‪static void Main(string[] args‬‬ ‫{‬ ‫‪.Threading.‬‬ ‫}‬ ‫}‬ ‫}‬ ‫يستخدم السطر االول الكلمة المحجوزة ‪ using‬للتصريح عن فضاء االسماء ‪ System‬أي أنه سيستخدم‬ ‫في الشيفرة هنا وبالتالي يمكن ألي فضاء أسماء في هذا الملف الوصول إلى فضاء االسماء ‪( System‬بما‬ ‫يتضمنه من أسماء) دون الحاجة لإلشارة إلى فضاء األسماء ‪ System‬بشكل صريح‪.Text‬‬ ‫‪using‬‬ ‫..Generic‬‬ ‫‪using‬‬ ‫.LT...using‬‬ ‫‪...‪System‬‬ ‫‪using‬‬ ‫.‬‬ ‫بالعودة إلى شيفرة أحد المشاريع السابقة وليكن ما قبل أخر مشروع نالحظ أن هناك استخدام لفضاءات‬ ‫االسماء‪:‬‬ ‫‪using‬‬ ‫.‪System.Console‬‬ ‫وبالمثل أيضا بالنسبة لباقي االسطر التي تستخدم الكلمة المحجوزة ‪.‪System..Linq‬‬ ‫‪using‬‬ ‫.NameThree‬‬ ‫من هنا نالحظ أن الكلمة المحجوزة ‪ using‬تساعدنا في اختصار كتابة االسماء التي تنتمي إلى فضاءات‬ ‫أسماء أخرى غير فضاء االسماء الحالي‪.NET‬ويتضمن جميع الوظائف‬ ‫األساسية التي نحتاجها لبرمجة تطبيقات ‪.‬‬ ‫في الحقيقة يمثل فضاء االسماء ‪ System‬فضاء األسماء الجذر لتطبيق ‪ .55 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .Collections.‪System...‪System.‪Using LT=LevelTow‬‬ ‫‪// name "NameThree" defined‬‬ ‫‪namespace LevelTow‬‬ ‫{‬ ‫‪// name "NameThree" defined‬‬ ‫}‬ ‫}‬ ‫‪//code in Global namespace‬‬ ‫عندئذ يمكننا الوصول إلى االسم ‪( NameThree‬الذي ينتمي إلى فضاء األسماء ‪ )LevelTow‬في فضاء‬ ‫األسماء الشامل أو فضاء أسماء ‪ LevelOne‬باالسم المحدد ‪.

.56 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .‬‬ ‫‪.‬‬ ‫كما ركزنا في هذا الفصل على شرح المتغيرات وتعرفنا على أنواع البيانات ومن ثم انتقلنا للتعرف على‬ ‫كيفية معالجة المتغيرات وتعرفنا على انواع العوامل الرياضية وكيفية التعامل مع القيم الحرفية النصية‬ ‫كما تعرفنا على كيفية التصريح عن فضاءات األسماء وكيف يتم استدعاء اسم من فضاء أسماء معشش‬ ‫ضمن فضاء أسماء أخر‪.. ‫الخالصة‪:‬‬ ‫‪Summary:‬‬ ‫لقد تناولنا في هذا الفصل كما ال باس به من المعلومات التي ستعتمد عليها بصورة كلية في تصميم تطبيقاتك‬ ‫االساسية بلغة ‪ C#‬لقد تناولنا الصيغة االساسية لكتابة شيفرة ‪ C#‬وقمنا بتحليل شيفرة تطبيقات ‪Console‬‬ ‫البسيطة‪.

‬‬ ‫إن كال الطريقتين تتطلب ان استخدام للمنطق البولياني لقد تعرفنا في الفصل السابق على نوع المعطيات‬ ‫البولياني إال أننا لم نخض فيه كثيرا لكن سوف نستخدم المتحوالت المنطقية (‪ )Bool‬بشكل مكثف في هذا‬ ‫الفصل وسوف نبدأ هذا الفصل بم ناقشة المقصود بالمنطق البولياني بحيث يفتح لنا ذلك الباب للحديث عن‬ ‫سيناريوهات التحكم في سير البرنامج‪. ‫الفصل الرابع‬ ‫التحكم يف سري الربنامج‬ ‫هناك شيء مشترك في جميع األمثلة البرمجية التي تناولناها حتى االن ال بد وأنك قد الحظته وأن تنفيذ‬ ‫البرنامج ينتقل من سطر إلى السطر الذي يليه مباشرة من بداية الشيفرة إلى نهايتها دون تجنب أي سطر‬ ‫إن اقتصرت التطبيقات على هذا النهج من التنفيذ فعندئذ سنكون محدودين جدا بما يمكننا فعله أثناء تصميم‬ ‫التطبيقات‪.‬‬ ‫سوف نتناول في هذا الفصل طريقتين للتحكم في سير البرنامج (أي التحكم في ترتيب تنفيذ االسطر‬ ‫البرمجية) هاتين الطريقتين هما‪:‬‬ ‫‪ -1‬التفرع (‪ ) branching‬حيث ستنفذ الشيفرة التي تحقق شرطا معينا باالعتماد على نتيجة تعبير‬ ‫ما‪.57 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .‬‬ ‫ال يمكن للمتحوالت من نوع ‪ Bool‬أن تحتوي إال على واحدة من إحدى القيمتين (‪ ) True،False‬يستخدم‬ ‫هذا النوع لتسجيل نتيجة عملية ما وبصورة عامة يستخدم نوع البيانات ‪ Bool‬لحفظ نتيجة مقارنة‬ ‫(‪ )comparison‬ما‪.‬‬ ‫‪ -2‬الحلقات(‪ )looping‬أي تكرار تنفيذ الشيفرة نفسها (لعدد محدد من المرات أو إلى أن يتحقق شرط‬ ‫ما)‪.‬‬ ‫تتطلب المقارنات المنطقية استخدام عوامل المقارنة البوليانية وتسمى أيضا بالعوامل العالئقية‬ ‫( ‪ )relational operators‬الجدول التالي يسرد هذه العوامل حيث أن المتحول ‪ var1‬من نوع ‪ Bool‬أما‬ ‫المتحولين ‪ vre2‬و‪ var3‬فهما من أي نوع كان‪:‬‬ ‫‪.

‬‬ ‫ويمكننا أن نقارن القيم المنطقية أيضا لتعطينا قيم منطقية أيضا‪:‬‬ ‫.‪isTrue = myBool ==true‬‬ ‫هنا سيأخذ المتحول ‪ isTrue‬القيمة ‪ true‬إذا كانت قيمة المتحول ‪ myBool‬هي ‪ true‬أيضا وإال فسيأخذ‬ ‫القيمة ‪.False‬‬ ‫كما يمكننا استخدام عوامل المقارنة على أنواع أخرى غير األنواع الرقمية كمقار نة السالسل النصية كما‬ ‫يلي‪:‬‬ ‫.‪bool isLessThan10‬‬ ‫.‪bool isHussam‬‬ ‫. ‫الناتج‬ ‫مثال‬ ‫العامل الفئة‬ ‫سيأخذ المتحول ‪ var1‬القيمة ‪ True‬إذا كانت قيمة المتحول‬ ‫‪ var2‬تساوي قيمة المتحول ‪ var3‬وإال فسيأخذ القيمة‬ ‫ثنائي ‪var1=var2==var3‬‬ ‫==‬ ‫‪False‬‬ ‫سيأخذ المتحول ‪ var1‬القيمة ‪ True‬إذا كانت قيمة المتحول‬ ‫‪ var2‬ال تساوي قيمة المتحول ‪ var3‬وإال فسيأخذ القيمة‬ ‫‪var1=var2!=var3‬‬ ‫ثنائي‬ ‫=!‬ ‫‪False‬‬ ‫سيأخذ المتحول ‪ var1‬القيمة ‪ True‬إذا كانت قيمة المتحول‬ ‫‪ var2‬أصغر من قيمة المتحول ‪ var3‬وإال فسيأخذ القيمة‬ ‫‪var1=var2<var3‬‬ ‫ثنائي‬ ‫<‬ ‫‪False‬‬ ‫سيأخذ المتحول ‪ var1‬القيمة ‪ True‬إذا كانت قيمة المتحول‬ ‫‪ var2‬أكبر من قيمة المتحول ‪ var3‬وإال فسيأخذ القيمة‬ ‫‪var1=var2>var3‬‬ ‫ثنائي‬ ‫>‬ ‫‪False‬‬ ‫سيأخذ المتحول ‪ var1‬القيمة ‪ True‬إذا كانت قيمة المتحول‬ ‫‪ var2‬أصغر أو تساوي قيمة المتحول ‪ var3‬وإال فسيأخذ‬ ‫ثنائي ‪var1=var2<=var3‬‬ ‫=<‬ ‫القيمة ‪False‬‬ ‫سيأخذ المتحول ‪ var1‬القيمة ‪ True‬إذا كانت قيمة المتحول‬ ‫‪ var2‬أكبر أو تساوي قيمة المتحول ‪ var3‬وإال فسيأخذ‬ ‫ثنائي ‪var1=var2>=var3‬‬ ‫=>‬ ‫القيمة ‪False‬‬ ‫ويمكننا أن نطبق العوامل المنطقية على المتغيرات أو على قيم حرفية مباشرة كما يلي‪:‬‬ ‫.‪bool isTrue‬‬ ‫.false‬‬ ‫‪.58 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ."‪isHussam = myString =="Hussam‬‬ ‫هنا سيأخذ المتحول ‪ is Hussam‬القيمة ‪ True‬إذا كانت السلسلة النصية في المتغير ‪ myString‬هي‬ ‫"‪ "Hussam‬دون عالمتي االقتباس طبعا‪.‪isLessThan10 = myVal < 10‬‬ ‫سيأخذ المتحول ‪ isLessThan10‬القيمة ‪ True‬إذا كانت قيمة المتحول ‪ myVal‬أقل من ‪ 19‬وإذا كانت‬ ‫قيمة المتحول ‪ myVal‬مساوية لـ ‪ 19‬أو أكبر منها فإن المتحول ‪ isLessThan10‬سيأخذ القيمة ‪.

false‬أن االمر مشابه للعامل || أيضا فإذا كانت‬ ‫قيمة أحد الحدين هي ‪ true‬فمن غير الضروري قراءة الحد الثاني ألنه مهما تكن قيمته فإن نتيجة العامل‬ ‫هي ‪ true‬عندئذ‪.59 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .‪bool isTrue‬‬ ‫.‫هناك عوامل منطقية أخرى خاصة بالمقارنات بين القيم والمتحوالت المنطقية فقط وهي مسرودة في‬ ‫الجدول التالي‪:‬‬ ‫الناتج‬ ‫مثال‬ ‫العامل الفئة‬ ‫سيأخذ المتحول ‪ var1‬القيمة ‪ true‬إذا كانت قيمة المتحول‬ ‫‪ var2‬هي ‪ false‬وسيأخذ القيمة ‪ false‬إذا كانت قيمة‬ ‫‪var1=! var2‬‬ ‫أحادي‬ ‫!‬ ‫‪ var2‬هي ‪true‬‬ ‫تسمى هذه العملية عملية النفي المنطقية ‪NOT‬‬ ‫‪ var1=var2 & var3‬سيأخذ المتحول ‪ var1‬القيمة ‪ true‬إذا كانت قيمة كال‬ ‫المتحولين ‪ var2‬و‪ var3‬هي ‪ true‬وسيأخذ القيمة ‪false‬‬ ‫أو‬ ‫&‬ ‫&& ‪ var1=var2‬إذا كانت قيمة أحد المتحولين هي ‪false‬‬ ‫ثنائي‬ ‫أو‬ ‫تسمى هذه العملية عملية ‪ AND‬المنطقية‬ ‫‪var3‬‬ ‫&&‬ ‫سيأخذ المتحول ‪ var1‬القيمة ‪ true‬إذا كانت قيمة أحد‬ ‫‪var1=var2 | var3‬‬ ‫|‬ ‫المتحولين ‪ var2‬أو‪ var3‬على االقل هي ‪ true‬وسيأخذ‬ ‫أو‬ ‫ثنائي‬ ‫أو‬ ‫القيمة ‪ false‬إذا كانت قيمة كال المتحولين هي ‪false‬‬ ‫‪var1=var2 || var3‬‬ ‫||‬ ‫تسمى هذه العملية عملية ‪ OR‬المنطقية‬ ‫سيأخذ المتحول ‪ var1‬القيمة ‪ true‬إذا كانت قيمة كال‬ ‫المتحولين ‪ var2‬و‪ var3‬غير متساوية أي أحدهما ‪true‬‬ ‫‪var1=var2 ^ var3‬‬ ‫و االخر ‪ false‬وسيأخذ القيمة ‪ false‬إذا كانت قيمة‬ ‫ثنائي‬ ‫^‬ ‫المتحولين متساوية‬ ‫تسمى هذه العملية عملية ‪ XOR‬المنطقية‬ ‫وبناء على ذلك فإن الشيفرة التالية مطابقة للشيفرة السابقة‪:‬‬ ‫.‬‬ ‫‪.‬‬ ‫إن االمر مختلف بالنسبة للعاملين & و | ألن هذين العاملين سيقرآن قيمة الحد األول والثاني مهما كانت‬ ‫قيمة أحدهما‪.‬‬ ‫فإذا كانت قيمة الحد االول للعامل && هي ‪ false‬فإنه من غير الضروري أن نقرأ قيمة الحد الثاني وذلك‬ ‫ألنه مهما تكن قيمة الحد الثاني فإن نتيجة العامل هي ‪ .‪isTrue = myBool & true‬‬ ‫الحظ أن للعامل & شكل أخر هو && إن نتيجة هذين العاملين (أي & و &&) هي نفسها إال أن هناك‬ ‫اختالف بين طريقة معالجة العامل الذي يقود على تحسين في األداء يقوم && بقراءة قيمة الحد األول‬ ‫أوال (وهو المتحول ‪ var2‬في المثال في الجدول) وحسب قيمة الحد األول سيقرر ما إذا كان من الضروري‬ ‫قراءة الحد الثاني أم ال‪.

WriteLine(true && false).60 . // true Console.3( ‫الشكل‬ . // false Console.2( ‫الشكل‬ false ‫ أن يكون كال الشرطين‬false ‫الحالة الوحيدة يكون فيها الناتج‬ :)Not( !‫مثال على‬ Console. // true )4.WriteLine(false || false).WriteLine(false || true).WriteLine(5 < 6 && 8 < 9).1( ‫الشكل‬ true ‫ أن يكون كال الشرطين‬true ‫الحالة الوحيدة يكون الناتج فيه‬ :)Or( || ‫مثال على‬ Console. // false Console.WriteLine(true && true). // false Console. //false Console.WriteLine(false && true). // true Console.WriteLine(!true).WriteLine(!false).WriteLine(false && false). // true )4.‫يستخدم هذا المعامل لنفى الحقيقة‬ . // true Console.WriteLine(true || true).& ‫سنجد مع المقارنات الكثيرة أن هناك تحسنا بسيطا في االداء عند استخدام العاملين && و || بدال من‬ . ‫ املهندس حسام الدين الرز‬:‫إعداد‬ .‫و | تباعا وبصورة عامة فإنني انصح باستخدام العاملين && و || متى كان ذلك ممكنا‬ :‫أمثلة‬ :)And( && ‫مثال على‬ Console. // false Console. // true Console.WriteLine(5 < 6 || 8 < 9). // true )4.WriteLine(true || false).

WriteLine(true ^ false‬‬ ‫‪// true‬‬ ‫.)‪Console.WriteLine(false ^ false‬‬ ‫‪// false‬‬ ‫.‬‬ ‫فاألرقام تخزن في الحاسوب على هيئة سلسلة من االصفار والوحدات فعلى سيبل المثال يمكننا تمثيل الرقم‬ ‫‪ 5‬بثالث خانات ثنائية ‪ 191:‬وذلك وفقا لقاعدة محددة تعرف بنظام العد الثنائي حيث تسمى كل خانة من‬ ‫خانات العدد الثنائي بالبت (‪ ) Bit‬وبالتالي فإننا عندما نستخدم هذه العوامل مع القيم الرقمية فإن هذا يعني‬ ‫أننا نقوم بتطبيق هذه العوامل على بتات القيمة بتمثيلها الثنائي‪.WriteLine(5 < 6 ^ 8 < 9‬‬ ‫‪// false‬‬ ‫.‬‬ ‫الجدول التالي يبين نتيجة تنفيذ العامل & على البتات‪:‬‬ ‫البت الناتج من &‬ ‫البت في الحد الثاني‬ ‫البت في الحد االول‬ ‫‪1‬‬ ‫‪1‬‬ ‫‪1‬‬ ‫‪9‬‬ ‫‪9‬‬ ‫‪1‬‬ ‫‪9‬‬ ‫‪1‬‬ ‫‪0‬‬ ‫‪9‬‬ ‫‪9‬‬ ‫‪0‬‬ ‫‪. ‫مثال على ^ (‪:)XOR‬‬ ‫.‬‬ ‫لقد الحظنا أن استخدام العوامل المنطقية مع المتحوالت المنطقية (البوليانية) أمر منطقي جدا في الحقيقة‬ ‫إن وجود عوامل مثل & و | لم يقتصر على المتحوالت البوليانية وإنما على المتحوالت والقيم العددية‬ ‫أيضا‪.WriteLine(false ^ true‬‬ ‫‪// true‬‬ ‫.)‪Console.WriteLine(true ^ true‬‬ ‫‪// false‬‬ ‫الشكل(‪)4.‬‬ ‫لنأخذ العامل & سيتم مقارنة كل بت في الحد األول مع البت المقابل له في الحد الثاني ونتيجة العامل هي‬ ‫مجموعة من البتات التي تمثل قيمة الخرج‪.)‪Console.61 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .)‪Console.)‪Console.4‬‬ ‫مالحظة‪ :‬الكتابة باللون األخضر هي الخرج كتبتها هكذا كي أذكرك بأننا يمكن أن نستخدم التعليقات ضمن‬ ‫سطر التعليمات أيضا‪.

‪op2=5‬‬ ‫.9‬‬ ‫على سبيل المثال لنأخذ الشيفرة التالية‪:‬‬ ‫.op2‬‬ ‫‪.op1 .‪op1=4‬‬ ‫.62 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .op2‬‬ ‫.‪int result .‪result = op1 & op2‬‬ ‫علينا هنا أن نأخذ التمثيل الثنائي للمتحولين ‪ op1‬و‪ op2‬بعين االعتبار فقيمة المتحول ‪ op1‬بالتمثيل الثنائي‬ ‫هي ‪ 199‬وقيمة المتحول ‪ op2‬وفقا لنظام العد الثنائي هي ‪ 101‬أن نتيجة تطبيق العامل & على المتحولين‬ ‫‪ op1‬و ‪ op2‬تتمثل بتطبيق العامل & على بتات التمثيل الثنائي للقيمتين وفقا لما يلي‪:‬‬ ‫‪ -1‬البت الموجود في أقصى يسار المتحول ‪ result‬يمثل نتيجة تطبيق العامل & على الب ت الموجود‬ ‫في أقصى يسار المتحول ‪ op1‬مع البت الموجود في أقصى يسار المتحول ‪op2‬‬ ‫‪ -2‬البت التالي في المتحول ‪ result‬يمثل نتيجة تطبيق العامل & على البت التالي الموجود في‬ ‫المتحول ‪ op1‬مع البت التالي الموجود في المتحول ‪op2‬‬ ‫‪ -3‬البت الموجود في أقصى يمين المتحول ‪ result‬يمثل نتيجة تطبيق العامل & على البت الموجود‬ ‫في أقصى يمين المتحول ‪ op1‬مع البت الموجود في أقصى يمين المتحول ‪. ‫والجدول التالي يبين نتيجة تنفيذ العامل | على البتات‪:‬‬ ‫البت الناتج من عملية |‬ ‫البت في الحد الثاني‬ ‫البت في الحد االول‬ ‫‪1‬‬ ‫‪1‬‬ ‫‪1‬‬ ‫‪1‬‬ ‫‪9‬‬ ‫‪1‬‬ ‫‪1‬‬ ‫‪1‬‬ ‫‪0‬‬ ‫‪9‬‬ ‫‪9‬‬ ‫‪0‬‬ ‫والجدول التالي يبين نتيجة تنفيذ العامل ^ على البتات‪:‬‬ ‫البت الناتج من عملية ^‬ ‫البت في الحد الثاني‬ ‫البت في الحد االول‬ ‫‪9‬‬ ‫‪1‬‬ ‫‪1‬‬ ‫‪1‬‬ ‫‪9‬‬ ‫‪1‬‬ ‫‪1‬‬ ‫‪1‬‬ ‫‪0‬‬ ‫‪9‬‬ ‫‪9‬‬ ‫‪0‬‬ ‫هناك عامل احادي أخر(~) يسمى بعامل ‪ NOT‬يستخدم على البتات يماثل ما يقوم به العامل االحادي!‬ ‫فما هو إال مقلوب العدد بنظام العد الثنائي كما يبين ذلك الجدول التالي‪:‬‬ ‫البت الناتج عن العملية المنطقية ~‬ ‫بت الحد‬ ‫‪9‬‬ ‫‪1‬‬ ‫‪1‬‬ ‫‪0‬‬ ‫ال حظ أنه يمكننا اعتبار القيمة ‪ true‬تمثل البت ذو القيمة ‪ 1‬والقيمة ‪ false‬تمثل البت ذو القيمة ‪.

‫و بالعودة إلى المتحولين ‪ op1‬و ‪ op2‬نالحظ أن البت الموجود في أقصى يسار المتحول ‪ op1‬و المتحول‬ ‫‪ op2‬هو ‪ 1‬في كال المتحولين و بالتالي فان قيمة البت الموجود في أقصى يسار المتحول ‪ result‬هي ‪1‬‬ ‫الن (‪ )1&1=1‬و البت التالي نالحظ أن قيمته ‪ 9‬في المتحول ‪ op1‬و ‪ op2‬و بالتالي فإن قيمته البت التالي‬ ‫للمتحول ‪ result‬هي ‪ 9‬ألن (‪ )0&0=0‬أما البت األخير فإن قيمته في المتحول ‪ op1‬هي ‪ 9‬و قيمته في‬ ‫المتحول ‪ op2‬هي ‪ 1‬و بالتالي فإن قيمة البت األخير في المتحول ‪ 9 result‬ألن (‪ )0&1=0‬و بناء على‬ ‫ذلك فإن التشفير الثنائي للمتحول ‪ result‬هو ‪ 199‬و هو ما يساوي القيمة ‪ 4‬بنظام العد الطبيعي‪.63 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .‬‬ ‫الشكل التالي يستعرض ذلك‪:‬‬ ‫العامل‬ ‫العدد بالعشري‬ ‫الترميز الثنائي‬ ‫‪4‬‬ ‫‪1‬‬ ‫‪9‬‬ ‫‪1‬‬ ‫&‬ ‫‪5‬‬ ‫‪1‬‬ ‫‪9‬‬ ‫‪0‬‬ ‫النتيجة‬ ‫‪4‬‬ ‫‪1‬‬ ‫‪9‬‬ ‫‪0‬‬ ‫واألمر مش ابه أيضا بالنسبة للعامل | فيما عدا أن النتيجة ستختلف كما يوضح ذلك الجدول التالي‪:‬‬ ‫العامل‬ ‫العدد بالعشري‬ ‫الترميز الثنائي‬ ‫|‬ ‫‪4‬‬ ‫‪1‬‬ ‫‪9‬‬ ‫‪1‬‬ ‫‪5‬‬ ‫‪1‬‬ ‫‪9‬‬ ‫‪0‬‬ ‫النتيجة‬ ‫‪5‬‬ ‫‪1‬‬ ‫‪9‬‬ ‫‪1‬‬ ‫يمكننا أن نستخدم العامل ^ بنفس الطريقة وفقا للجدول التالي‪:‬‬ ‫العامل‬ ‫العدد بالعشري‬ ‫الترميز الثنائي‬ ‫^‬ ‫‪4‬‬ ‫‪1‬‬ ‫‪9‬‬ ‫‪1‬‬ ‫‪5‬‬ ‫‪1‬‬ ‫‪9‬‬ ‫‪0‬‬ ‫النتيجة‬ ‫‪1‬‬ ‫‪9‬‬ ‫‪9‬‬ ‫‪1‬‬ ‫يمكننا أن نستخدم العامل األحادي ~ بنفس الطريقة على أحد العددين وفق الجدول التالي‪:‬‬ ‫العامل‬ ‫العدد بالعشري‬ ‫الترميز الثنائي‬ ‫~‬ ‫‪5‬‬ ‫‪1‬‬ ‫‪9‬‬ ‫‪1‬‬ ‫النتيجة‬ ‫‪2‬‬ ‫‪9‬‬ ‫‪1‬‬ ‫‪0‬‬ ‫في الحقيقة أن معكوس القيمة ‪ 5‬في نظام العد الثنائي هو ‪ 6-‬وليس ‪ 2‬إال أن المثال السابق لتوضيح حيث‬ ‫تمثل القيمة ‪ 6-‬في نظام العد الثنائي ب ‪ 16‬خانة أو ‪ 32‬خانة أو ‪ 64‬خانة وهذا تمثيل العدد ‪ 6-‬وفق ‪16‬‬ ‫خانة‪1111 1111 1111 1919 :‬‬ ‫‪.

WriteLine(x & y).1‬‬ ‫.ReadKey‬‬ ‫المعامل | (‪:)Or‬‬ ‫يكون الناتج ‪ 1‬إذا كان أحد الشرطين ‪.1‬‬ ‫.‪int x = 13‬‬ ‫‪// 13‬‬ ‫‪00000000 00000000 00000000 00001101‬‬ ‫. // 8‬‬ ‫‪1000‬‬ ‫.‪int y = 9‬‬ ‫‪// 9‬‬ ‫‪01001‬‬ ‫‪Console. // 27‬‬ ‫‪11011‬‬ ‫.WriteLine(x | y).WriteLine(~x‬‬ ‫‪// -14‬‬ ‫‪11111111 11111111 11111111 11110010‬‬ ‫.)‪Console.‪int x = 26‬‬ ‫‪//‬‬ ‫‪26‬‬ ‫‪11010‬‬ ‫.ReadKey‬‬ ‫المعامل ~ (‪:)Complement Notation‬‬ ‫هذا المعامل يسمى أيضا بالمتمم أي يجعل ‪ 1‬صفر ويجعل ‪ 9‬واحد‪.)(‪Console.‬‬ ‫.ReadKey‬‬ ‫‪.‪int y = 9‬‬ ‫‪// 9‬‬ ‫‪01001‬‬ ‫‪Console.WriteLine(x ^ y).64 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .‪int y = 9‬‬ ‫‪//‬‬ ‫‪9‬‬ ‫‪01001‬‬ ‫‪Console.)(‪Console.‪int x = 26‬‬ ‫‪// 26‬‬ ‫‪11010‬‬ ‫.‪int x = 26‬‬ ‫‪// 26‬‬ ‫‪11010‬‬ ‫. ‫أمثلة أخرى‪:‬‬ ‫المعامل & (‪:)And‬‬ ‫يكون الناتج ‪ 1‬في حالة واحدة إذا كان كال الشرطين ‪.)(‪Console.1‬‬ ‫.)(‪Console. // 19‬‬ ‫‪10011‬‬ ‫.ReadKey‬‬ ‫المعامل ^ (‪:)XOR‬‬ ‫يكون الناتج واحد في حالة واحدة إذا كان أحد الطرفين فقط ‪.

WriteLine(!false‬‬ ‫‪ -3‬نفذ التطبيق بالضغط على مفتاح ‪ Ctrl+F5‬فيظهر الشكل (‪.‪result4 = ~ myNumber2‬‬ ‫.WriteLine("result3={0}". result4‬‬ ‫.65 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .‬‬ ‫في االسطر االربعة التالية قمنا بإظهار الخرج على نافذة ‪ Console‬كما تعلمنا سابقا‪.)4-5‬‬ ‫الشكل (‪)4.)‪Console.‬‬ ‫‪-4‬‬ ‫‪.result2.result3.Console Bitwise operators‬‬ ‫‪ -2‬أضف الشيفرة البرمجية التالية إلى محرر نصوص ‪.)‪Console.‪result3 = myNumber1 ^ myNumber2‬‬ ‫. result1‬‬ ‫.int‬‬ ‫‪-2‬‬ ‫في األسطر األربعة التالية قمنا بتطبيق العمليات المنطقية على البتات واسناد كل عملية من‬ ‫‪-3‬‬ ‫العمليات لمتحول من المتحوالت االربعة التي صرحنا عنها في السطر الثاني‪. result4‬‬ ‫.)‪Console.‬‬ ‫‪-1‬‬ ‫في السطر الثاني قمنا بالتصريح عن أربعة متحوالت من النوع ‪.)‪Console.‪int myNumber1 = 4.‪int result1. ‪result1 =myNumber1 & myNumber2‬‬ ‫. ‪result2 =myNumber1 | myNumber2‬‬ ‫. result3‬‬ ‫. myNumber2 = 5‬‬ ‫.C#‬‬ ‫.‫هذا المثال على اعتبار أن النظام ‪ 32‬بت يعنى ‪ 32‬خانة تحتوي أما على صفر أو واحد هو تمثيل الرقم‬ ‫‪ 13‬في النظام ‪ 32‬يكون بهذا الشككككل باسكككتخدام المعامل ~ وعكس الواحد صكككفر والصكككفر واحد أصكككبح‬ ‫الناتج بالسالب ‪ 14-‬طبعا ولو كتب هذا المعامل مرتين يعود بنفس الرقم ‪13 = ~~x‬‬ ‫تطبيق حول العوامل الم نطقية والعوامل الخاصة بالبتات‪:‬‬ ‫‪ -1‬قم بإنشاء تطبيق ‪ Console‬جديد باسم ‪. result2‬‬ ‫.WriteLine("result1={0}".WriteLine(!true‬‬ ‫.)‪Console.5‬‬ ‫كيفية العمل‪:‬‬ ‫‪How it Works:‬‬ ‫في الشيفرة التي أضفناها قمنا بما يلي‪:‬‬ ‫في السطر االول من الشيفرة قمنا بالتصريح عن متحولين من النوع ‪ int‬واسناد قيم لهما‪.WriteLine("result4={0}".)‪Console.WriteLine("result2={0}".

49‬‬ ‫وبصورة مشابهة فإن عملية االزاحة إلى اليمين أي العامل >> تعني قسمة المتحول ‪ var2‬على القيمة ‪2‬‬ ‫لعدد ‪ var3‬من المرات‪:‬‬ ‫.‪var1=var2>>2‬‬ ‫لن نستخدم هذا النوع من العوامل في شيفرتنا البرمجية إال نادرا إال أنه من الواجب عليك أن تتعرف‬ ‫عليها‪.‬‬ ‫‪.‪var1=var2 >> 1‬‬ ‫هنا سيتضمن المتحول ‪ var1‬القيمة ‪ 5‬وذلك ألن إزاحة العدد الثنائي "‪ " 1919‬إلى اليمين مرة واحدة‬ ‫يساوي العدد الثنائي "‪ "191‬أي ‪ 5‬بالنظام العشري‪. var2 = 10‬‬ ‫.var3=2‬‬ ‫.66 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ . var2 = 10.‪var1=var2<<var3‬‬ ‫هنا سيأخذ المتحول ‪ var1‬القيمة ‪ 49‬ولكن كيف ذلك؟‬ ‫إن التمثيل الثنائي لقيمة المتحول ‪ var2‬هي (‪ )1919‬وبإزاحة بتات هذه القيمة إلى اليسار بمقدار بتين‬ ‫اثنين سيصبح التمثيل الثاني بالشكل (‪ )191999‬والذي يساوي القيمة ‪ 49‬بالنظام العشري في الحقيقة ان‬ ‫عملية االزاحة إلى اليسار أي العامل << تمثل ضرب قيمة المتحول ‪ var2‬بالقيمة ‪ 2‬لعدد ‪var3‬من‬ ‫المرات أي أن إزاحة القيمة ‪ 19‬بمقدار ‪ 2‬يعني ضرب ‪ 19‬بالقيمة ‪ 4‬أي ‪.‪int var1.‫‪ -5‬في السطرين التاليين قمنا بإظهار نتيجة تطبيق العامل االحادي (!) على القيمتين البوليانيتان‬ ‫(‪ true‬و‪)false‬‬ ‫‪ -6‬السطر االخير يمكننا من مشاهدة الخرج على شاشة ‪.‪int var1.‪int var1.‬‬ ‫أما في المثال التالي فإن قيمة المتحول ‪ var1‬هي ‪:2‬‬ ‫.Console‬‬ ‫باإلضافة للعوامل السابقة فإن هناك عامالن لم نتحدث عنهما حتى االن الجدول التالي يوضح هذين‬ ‫العاملين‪:‬‬ ‫الناتج‬ ‫مثال‬ ‫العامل الفئة‬ ‫سيأخذ المتحول ‪ var1‬قيمة المتحول ‪ var2‬بعد إزاحة‬ ‫‪var1=var2>>var3‬‬ ‫ثنائي‬ ‫>>‬ ‫بتات قيمته إلى اليمين بقيمة المتحول ‪var3‬‬ ‫سيأخذ المتحول ‪ var1‬قيمة المتحول ‪ var2‬بعد إزاحة‬ ‫‪var1=var2<<var3‬‬ ‫ثنائي‬ ‫<<‬ ‫بتات قيمته إلى اليسار بقيمة المتحول ‪var3‬‬ ‫تسمى هذه العملية عادة بعملية إزاحة البتات ( ‪ )bitwise shift operators‬البد وأنك لم تفهم تماما ما‬ ‫يقوم به هذان العامالن لذا سوف نستعرضهما بمثال بسيط‪:‬‬ ‫. var2 = 10‬‬ ‫.

67 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .C#‬‬ ‫)‪static void Main(string[] args‬‬ ‫{‬ ‫.)4-6‬‬ ‫الشكل (‪)4.)‪Console.)‪Console.‬‬ ‫. myInt & 10‬‬ ‫.WriteLine("translater to left 10={0}"..WriteLine("integer less than 10? {0}".WriteLine("translater to right 10={0}".)‪Console.6‬‬ ‫كيفية العمل‪:‬‬ ‫‪How it Works:‬‬ ‫‪.‫إن أخر مجموعة من العوامل سوف نتعرض لها في هذا القسم هي تلك العوامل نفسها التي تناولناها سابقا‬ ‫متضمنة عامل اإللحاق وهي مشابهة لعوامل االلحاق الرياضية التي تحدثنا عنها في الفصل السابق (مثل‬ ‫=‪ +‬و =*‪ ).WriteLine("bitwise and of integer and 10 ={0}".ToInt32(Console.)‪Console. 10 >> myInt‬‬ ‫}‬ ‫‪ -3‬نفذ التطبيق بالضغط على مفتاح ‪ Ctrl+F5‬وأدخل عددا صحيحا عند طلب ذلك كما في الشكل‬ ‫(‪..WriteLine("enter an integer:‬‬ ‫. 10 << myInt‬‬ ‫.)‪0 <= myInt && myInt <= 5‬‬ ‫.WriteLine("integer between 0 and 5? {0}".‬الجدول التالي يسرد هذه العوامل‪:‬‬ ‫الناتج‬ ‫مثال‬ ‫الفئة‬ ‫العامل‬ ‫اسناد التعبير ‪ var1&var2‬للمتحول ‪var1‬‬ ‫‪var1&=var2‬‬ ‫ثنائي‬ ‫=&‬ ‫اسناد التعبير ‪ var1|var2‬للمتحول ‪var1‬‬ ‫‪var1|=var2‬‬ ‫ثنائي‬ ‫=|‬ ‫اسناد التعبير ‪ var1^var2‬للمتحول ‪var1‬‬ ‫‪var1^=var2‬‬ ‫ثنائي‬ ‫=^‬ ‫اسناد التعبير ‪ var1<<var2‬للمتحول ‪var1‬‬ ‫‪var1<<=var2‬‬ ‫ثنائي‬ ‫=<<‬ ‫اسناد التعبير ‪ var1>>var2‬للمتحول ‪var1‬‬ ‫‪var1>>=var2‬‬ ‫ثنائي‬ ‫=>>‬ ‫تطبيق حول استخدام العوامل المنطقية والعوامل الخاصة بالبتات‪:‬‬ ‫‪ -1‬قم بإنشاء تطبيق ‪ Console‬جديد باسم ‪.Console Bitwise operators2‬‬ ‫‪ -2‬أضف الشيفرة البرمجية التالية إلى محرر نصوص ‪.ReadLine‬‬ ‫.))(‪int myInt = Convert.)"‪Console. myInt < 10‬‬ ‫‪Console.

Convert.myInt & 10‬‬ ‫في السطر السادس قمنا بإظهار ناتج عملية منطقية خاصة بالبتات على شاشة ‪ Console‬وذلك‬ ‫‪-6‬‬ ‫بإزاحة بتات العدد ‪ 19‬لليسار بقيمة العدد المدخل عبر التعليمة ‪. + )3‬‬ ‫(‪>> . <= . > .ToInt32(Console.‬‬ ‫االسبقية األعلى‬ ‫!‪~ .‬األحادية) ‪.68 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .[0-5‬‬ ‫في السطر الخامس قمنا بإظهار ناتج عملية منطقية خاصة بالبتات على شاشة ‪ Console‬وذلك‬ ‫‪-5‬‬ ‫بمقارنة بتات الرقم المدخل مع العدد ‪ 19‬عبر التعليمة ‪.10 << myInt‬‬ ‫في السطر السابع قمنا بإظهار ناتج عملية منطقية خاصة بالبتات على شاشة ‪ Console‬وذلك‬ ‫‪-7‬‬ ‫بإزاحة بتات العدد ‪ 19‬لليمين بقيمة العدد المدخل عبر التعليمة ‪. ‫في الشيفرة التي أضفناها قمنا بما يلي‪:‬‬ ‫في السطر االول من الشيفرة تظهر رسالة على شاشة ‪ Console‬تطلب من المستخدم ادخال عدد‬ ‫‪-1‬‬ ‫صحيح "‪. ++ )1‬كبادئات) ‪( . == )6‬‬ ‫(‪& )7‬‬ ‫(‪^ )8‬‬ ‫(‪| )9‬‬ ‫(‪&& )10‬‬ ‫‪.. / .10 >> myInt‬‬ ‫لقد أصبح لدينا اآلن عددا ال بأس به من الع وامل وكما للعوامل الرياضية موقع من جدول أسبقية العوامل‬ ‫فإن للعوامل المنطقية موقع أيضا في هذا الجدول وبالتالي فإن جدول أولوية العوامل يصبح بالصورة‬ ‫التالية‪:‬‬ ‫(‪( -..‬‬ ‫(‪% .ReadLine‬‬ ‫في السطر الثالث من الشيفرة قمنا بإظهار قيمة منطقية (‪ true‬أو ‪ )false‬على شاشة ‪Console‬‬ ‫‪-3‬‬ ‫بناء على المقارنة المنطقية ‪ myInt < 10‬أي هل العدد المدخل أصغر من ‪.19‬‬ ‫في السطر الرابع من الشيفرة قمنا بإظهار قيمة منطقية (‪ true‬أو ‪ )false‬على شاشة ‪Console‬‬ ‫‪-4‬‬ ‫بناء على المقارنة المنطقية ‪ 0 <= myInt && myInt <= 5‬أي هل العدد المدخل يقع ضمن‬ ‫المجال المغلق ]‪. << )4‬‬ ‫(‪>= ."enter an integer:‬‬ ‫في السكككطر الثاني قمنا بالتصكككريح عن متحول باسكككم ‪ myInt‬من النوع ‪ int‬قيمته تسكككاوي قيمة‬ ‫‪-2‬‬ ‫دخككككل الكككمسككككككككككتكككخككككدم بكككعككككد تككككحكككويككككل الككككدخككككل إلكككى الكككنكككوع ‪ int32‬عكككبكككر الكككتكككعكككلكككيككككمككككة‬ ‫)(‪.+ . * )2‬‬ ‫(‪.. < )5‬‬ ‫(‪!= .

myLabel1‬‬ ‫‪ -3‬كتابة قيمة المتحول ‪ myInteger‬على نافذة ‪. *= .5‬‬ ‫‪ -2‬ستقاطع التعليمة ‪ goto‬التنفيذ المتسلسل للشيفرة وستنقل التحكم بالبرنامج إلى السطر ذو العنوان‬ ‫‪.‪int myInteger = 5‬‬ ‫. myInteger‬‬ ‫.)‪Console. ^= . -= .‪int myInteger = 5‬‬ ‫. myInteger‬‬ ‫سيتم تنفذ هذه الشيفرة وفقا لما يلي‪:‬‬ ‫‪ -1‬التصريح عن المتحول ‪ myInteger‬بالنوع ‪ int‬واسناد قيمة له تساوي ‪.69 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .)‪Console.‬‬ ‫تسمح لنا لغة ‪ C#‬بعنونة أ سطر الشيفرة البرمجية وذلك بغرض القفز إلى تلك األسطر باستخدام تعليمة‬ ‫‪ goto‬إن لذلك فوائد ومشاكل فالفائدة الرئيسية هي أن هذه التعليمة تمثل طريقة سهلة جدا للتحكم في‬ ‫الشيفرة المنفذة أما المشكلة الرئيسية فهي أن استخدام هذه التعليمة بشكل مكثف سيؤدي لتشكيل شيفرة‬ ‫برمجية صعبة القراءة والفهم‪.WriteLine("myInteger ={0}". += .goto‬‬ ‫إ ليك الشيفرة التالية التي تستعرض بعضا من االمور المربكة الستخدام تعليمة ‪:goto‬‬ ‫‪Start:‬‬ ‫.WriteLine("myInteger ={0}". %= .‪goto myLabel1‬‬ ‫. ++ )13‬كلواحق)‬ ‫األسبقية األدنى‬ ‫لقد احتوى الجدول اآلن على مستويات أكثر من قبل إال أنه يصف أسبقية هذه العوامل على بعضها البعض‬ ‫بشكل صريح‪. &= .Console‬‬ ‫لتعليمة ‪ goto‬استخداماتها إال أنها يمكن أن تجعل األمور أكثر إرباكا مما هي عليه خصوصا عند كتابة‬ ‫مئات االسطر البرمجية التي تتضمن تعليمتين أو ثالثة للقفز ‪.‬‬ ‫والمثال التالي سيوضح ألية عمل هذه التعليمة‪:‬‬ ‫.‬‬ ‫(‪( -. /= . = )12‬‬ ‫‪|= . >>= . ‫(‪|| )11‬‬ ‫(‪<<= .‪goto addVal‬‬ ‫‪writeResult:‬‬ ‫..‪myInteger += 10‬‬ ‫‪myLabel1:‬‬ ‫.‪goto Start‬‬ ‫‪.

switch‬‬ ‫‪.‬‬ ‫سوف نتناول في هذا القسم ثالثة تقنيات متوفرة في لغة ‪ C#‬للتفرع‪.‪myInteger += 10‬‬ ‫.‪goto writeResult‬‬ ‫إن هذه الشيفرة سليمة تماما إال أن قراءتها صعبة للغاية ويمك نك أن تتحقق من ذلك إذا حاولت تتبع سير‬ ‫البرنامج والكيفية التي ينفذ وفقها الشكل (‪ )4-7‬يبن طريقة تنفيذ البرنامج‪.‬‬ ‫‪ -2‬تعليمة ‪.7‬‬ ‫سوف نأتي على هذه التعليمة الحقا حيث أن لها استخدامات في بنى أخرى من هذا الفصل‪. ‫‪addVal:‬‬ ‫.if‬‬ ‫‪ -3‬تعليمة ‪.70 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .‬‬ ‫يمثل التفرع حدث التحكم باألسطر البرمجية التي سيتم تنفيذها إن السطر الذي سيتم االنتقال إليه لتنفيذه‬ ‫يعتمد على تحقيق شرط معين وذلك وفقا لتعليمة شرطية (‪ )conditional statement‬تعتمد نتيجة هذه‬ ‫التعليمة الشرطية على المقارنة بين قيمة اختيارية وبين قيمة أو أكثر باستخدام المنطق البولياني‪.‬‬ ‫الشكل (‪)4.‬‬ ‫‪ -1‬العامل ثالثي الحدود‪.

C#‬‬ ‫)‪static void Main(string[] args‬‬ ‫{‬ ‫."‪"Greater than or equal to 10‬‬ ‫.))(‪myInt = Convert."‪"Greater than or equal to 10‬‬ ‫إن نتيجة العامل الثالثي هنا هي إحدى السلسلتين النصيتين فإحداهما يمكن أن تمثل قيمة المتحول النصي‬ ‫‪ resultString‬وذلك بناء على نتيجة المقارنة )‪ (myInt < 10‬فإذا كانت قيمة ‪ myInt‬أقل تماما من ‪19‬‬ ‫فستسند السلسلة النصية األولى إلى المتحول ‪ resultString‬إذا كانت قيمة ‪ myInt‬أكبر أو تساوي ‪10‬‬ ‫فستسند السلسلة النصية الثانية إلى المتحول ‪ resultString‬أي إذا كانت نتيجة الشرط هي ‪ true‬فإن الحد‬ ‫الثاني سيمثل نتيجة العامل وإن كانت نتيجة الشرط هي ‪ false‬فإن الحد الثالث سيمثل نتيجة العامل‪.‬‬ ‫للعامل ثالثي الحدود الصيغة التالية‪:‬‬ ‫> ‪<test> ? < resultIfTrue > : < resultIfFalse‬‬ ‫هنا سيتم تنفيذ التعبير الممثل بـ >‪ <test‬والذي سيمثل تعبيرا منطقيا يعطي قيمة بوليانية (إما ‪ true‬أو‬ ‫‪ )false‬و بناء على ذلك فإن نتيجة العامل إما ستكون > ‪ < resultIfTrue‬أو ‪< resultIfFalse‬‬ ‫>فيمكننا أن نستخدم العامل بالصورة التالية‪:‬‬ ‫‪string resultString = (myInt < 10) ? "Less than 10":‬‬ ‫.WriteLine("enter number‬‬ ‫.‫إن أبسط أسلوب للقيام بعملية مقارنة تقتضي باستخدام العامل ثالثي الحدود (‪ )temary operator‬ويسمى‬ ‫بالعامل الشرطي (‪ )conditional operator‬الذي نوهنا عنه في الفصل السابق لقد تعرفنا على طريقة‬ ‫عمل العوامل األحادية التي تطبق على حد واحد وكذلك العوامل الثنائية التي تطبق على حدين ولذا لن‬ ‫يكون العامل ذو الحدود الثالثة بشيء غريب‪.)4-8‬‬ ‫‪. resultString‬‬ ‫}‬ ‫‪ -3‬نفذ التطبيق بالضغط على مفتاح ‪ Ctrl+F5‬وأدخل عددا صحيحا أصغر من ‪19‬عند طلب ذلك ثم‬ ‫اضغط ‪ enter‬فتظهر النتيجة كما في الشكل (‪.‪int myInt‬‬ ‫.ToInt32(Console.WriteLine("resultString={0}".‬‬ ‫إن هذا العامل جيد جدا بالنس بة لعمليات االسناد المشروطة كما وجدنا هذا في المثال السابق إال أنه غير‬ ‫مناسب لتنفيذ أسطر برمجية عديدة اعتمادا على عملية مقارنة وللقيام بذلك فإن علينا استخدام تعليمة ‪.ReadLine‬‬ ‫‪string resultString = (myInt < 10) ? "Less than 10" :‬‬ ‫.71 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .if‬‬ ‫تطبيق حول العامل ثالثي الحدود‪:‬‬ ‫‪ -1‬قم بإنشاء تطبيق ‪ Console‬جديد باسم ‪.)"‪Console.)‪Console.Console Ternary Operator‬‬ ‫‪ -2‬أضف الشيفرة البرمجية التالية إلى محرر نصوص ‪.

ToInt32(Console."‪"Greater than or equal to 10‬‬ ‫حيث يقوم هذا التعبير بالمقارنة ب ين قيمة الدخل والعدد ‪ 19‬إذا كان أصغر من ‪ 19‬فأن المتحول‬ ‫‪ resultString‬يقوم بتخزين النص "‪ "Less than 10‬وإذا كان أكبر أو يساوي ‪ 19‬فإن هذا المتحول‬ ‫يخزن القيمة "‪"Greater than or equal to 10‬‬ ‫‪ -5‬في السطر الخامس يتم إظهار النص المسند للمتحول ‪ resultString‬على شاشة ‪.enter number‬‬ ‫في السطر الثالث قمنا بإسناد قيمة الدخل إلى المتحول ‪ myInt‬بعد تحويل الدخل إلى النوع ‪int32‬‬ ‫‪-3‬‬ ‫عبر التعليمة )(‪. ‫الشكل (‪)4.9‬‬ ‫كيفية العمل‪:‬‬ ‫‪How it Works:‬‬ ‫في الشيفرة التي أضفناها قمنا بما يلي‪:‬‬ ‫في السطر االول قمنا بالتصريح عن متحول ‪ myInt‬من النوع ‪.ReadLine‬‬ ‫في السطر الرابع قمنا بالتصريح عن متحول باسم ‪ resultString‬من نوع ‪ string‬ومن ثم اسندنا‬ ‫‪-4‬‬ ‫له عامل ثالثي الحدود باستخدام التعبير‬ ‫‪resultString = (myInt < 10) ? "Less than 10":‬‬ ‫.Console‬‬ ‫‪.72 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .8‬‬ ‫‪ -4‬أعد تنفيذ التطبيق بالضغط على مفتاح ‪ Ctrl+F5‬وأدخل عددا صحيحا أكبر من ‪19‬عند طلب ذلك‬ ‫ثم اضغط ‪ enter‬فتظهر النتيجة كما في الشكل (‪.Convert.)4-9‬‬ ‫الشكل (‪)4.int‬‬ ‫‪-1‬‬ ‫في السطر الثاني من الشيفرة تظهر رسالة على شاشة ‪ Console‬تطلب من المستخدم ادخال عدد‬ ‫‪-2‬‬ ‫صحيح ‪.

> ‪< Code executed if < test > is true‬‬ ‫}‬ ‫‪Else‬‬ ‫{‬ ‫.> ‪< Code executed if < test > is false‬‬ ‫}‬ ‫وكمثال بسيط لنعيد كتابة المثال الذي كتبناه باستخدام العامل الشرطي الثالثي ‪ ?:‬في القسم التالي باستخدام‬ ‫تعليمة ‪:if‬‬ ‫‪.73 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .‬‬ ‫تقوم صيغة التعليمة تلك بتنفيذ شيفرة عند تحقق شرط محدد ولكن إذا لم يتحقق هذا الشرط عندئذ سينتقل‬ ‫التنفيذ إلى السطر التالي وهناك صيغة موسعة لتعليمة ‪ if‬تمكننا من تنفيذ شيفرة معينة أخرى عند عدم‬ ‫تحقق الشرط وتلك الصيغة لها الشكل التالي‪:‬‬ ‫)> ‪If (< test‬‬ ‫.> ‪< Code executed if < test > is true‬‬ ‫سيتم تنفيذ السطر البرمجي لتعليمة ‪ if‬إذا أخذ التعبير البولياني > ‪< test‬القيمة ‪ true‬فقط وإن كانت نتيجة‬ ‫التعبير > ‪ < test‬هي ‪ false‬فلن ينفذ سطر تعليمة ‪ if‬عندئذ‪.‬‬ ‫الص يغة البسيطة لتعليمة ‪ if‬لها الشكل التالي‪:‬‬ ‫)> ‪If (< test‬‬ ‫.> ‪< Code executed if < test > is false‬‬ ‫يمكننا أن ننفذ كتلة برمجية كاملة (أي عدة أسطر من الشيفرة) ضمن تعليمة ‪ if‬وذلك وفقا للصيغة‪:‬‬ ‫)> ‪If (< test‬‬ ‫{‬ ‫.‫لتعليمة ‪ if‬جوانب استعمال عديدة ومفيدة لصنع القرارات فبعكس العامل ‪ ?:‬ال تعيد تعليمة ‪ if‬نتيجة محددة‬ ‫(وبالتالي ال يمكننا استخدامها لإلسناد) وبدال من ذلك فإننا سنستخدم التعليمة لتنفيذ تعليمة أو تعليمات‬ ‫أخرى عند تحقق شرط معين‪.> ‪< Code executed if < test > is true‬‬ ‫‪Else‬‬ ‫.

resultString). if (var1 < var2) comparison = "less than". Console.WriteLine("resultString ={0}".ReadLine()). double var1 = Convert.WriteLine("enter number:"). comparison).ReadLine()).ReadLine()).WriteLine("enter a number:").‫وتشاهد نتائج التنفيذ‬ :if ‫تطبيق حول استخدام تعليمة‬ .74 .ToInt32(Console. } ‫ ثم قم بإدخال العدد األول عندما يطلب منك البرنامج‬Ctrl+F5 ‫ نفذ التطبيق بالضغط على مفتاح‬-3 . if (myInt < 10) resultString ="Less than 10" . int myInt.Read().)4-19( ‫ فيظهر الشكل‬Enter ‫ ثم قم بإدخال العدد الثاني ومن ثم اضغط‬Enter ‫ثم اضغط‬ )4-19( ‫الشكل‬ . } Console.ToDouble(Console.WriteLine("the first number is {0} the second number" . Console. Console. else { if (var1 == var2) comparison = "equal to". ‫ املهندس حسام الدين الرز‬:‫إعداد‬ .WriteLine("enter another number:"). Console.ToDouble(Console. ‫على الرغم من أن هذه الشيفرة البرمجية تحوي أسطر برمجية إضافية أي أن الشيفرة أكبر إال اننا نالحظ‬ ‫أنه يمكن قراءة هذه الشيفرة بسهولة أكثر من تعليمة العامل الثالثي يمكنك تطبيق هذا المثال بمفردك‬ . string resultString. double var2 = Convert.Console if Statement ‫ جديد باسم‬Console ‫ قم بإنشاء تطبيق‬-1 . else comparison = "greater than". Console.C# ‫ أضف الشيفرة البرمجية التالية إلى محرر نصوص‬-2 static void Main(string[] args) { String comparison. myInt = Convert. else resultString ="Greater than or equal to 10".

ToDouble(Console.Convert."‪comparison = "less than‬‬ ‫)‪if (var1 == var2‬‬ ‫."greater than‬‬ ‫يعمل السطر األخير على إظهار نتيجة المقارنة على شاشة ‪Console‬‬ ‫‪-7‬‬ ‫لقد استخدمنا هنا تعشيش تعليمة ‪ if‬ويمكننا أن نعيد كتابة قسم تعليمة ‪ if‬السابقة كما يلي‪:‬‬ ‫)‪if (var1 < var2‬‬ ‫.ReadLine‬‬ ‫في السكطر الرابع تظهر رسكالة على شكاشة ‪ Console‬تطلب من المستخدم ادخال عدد ‪enter‬‬ ‫‪-4‬‬ ‫‪another number:‬‬ ‫في السكككطر الخامس قمنا بالتصكككريح عن متحول جديد باسكككم ‪ var2‬وأسكككندنا له قيمة الدخل بعد‬ ‫‪-5‬‬ ‫تكككككككحكككككككويكككككككل الكككككككدخكككككككل إلكككككككى الكككككككنكككككككوع ‪ Double‬عكككككككبكككككككر الكككككككتكككككككعكككككككلكككككككيكككككككمكككككككة‬ ‫))(‪.‬‬ ‫لقد تفحصكنا في المثال السكابق ثالثة شروط استخدمت المتحول ‪ var1‬لقد غطت هذه الشروط كافة القيم‬ ‫الممكنكة لهكذا المتحول قكد تحتكاج ف ي العديد من األحيان إلى تفحص قيم محددة للمتحول ‪ var1‬كأن نقول‬ ‫‪. ‫كيفية العمل‪:‬‬ ‫‪How it Works:‬‬ ‫في الشيفرة التي أضفناها قمنا بما يلي‪:‬‬ ‫في السطر االول قمنا بالتصريح عن متحول ‪ comparison‬من النوع ‪.ToDouble(Console.enter a number‬‬ ‫في السطر الثالث قمنا بالتصريح عن متحول جديد باسم ‪ var1‬وأسندنا له قيمة الدخل بعد تحويل‬ ‫‪-3‬‬ ‫الككككدخككككل إلكى الكنكوع ‪( Double‬عشكككككككري أي يكقكبككككل فككككاصكككككككلككككة عككككائكمككككة) عكبكر الكتكعكليمككككة‬ ‫))(‪."‪comparison = "equal to‬‬ ‫) ‪if (var1 >var2‬‬ ‫إال أنني ال أفضل استخدام هذه الطريقة وذلك ألننا هنا نقوم ب ثالث عمليات مقارنة بغض النظر عن قيمة‬ ‫المتحولين ‪ var1‬و‪ var2‬أما في الطريقة األولى فإن هناك عمليتا مقارنة كحد اقصككككى وتلك مسككككألة تؤثر‬ ‫في االداء بالنسبة للتطبيقات التي تكون فيها سرعة التنفيذ أمرا حاسما‪.ReadLine‬‬ ‫تعمكل تعليمة ‪ if‬على المقارنة بين قيمة المتحولين ‪ var1‬و‪ var2‬فإذا كانت قيمة ‪ var1‬أصكككككككغر‬ ‫‪-6‬‬ ‫من ‪ var2‬عندئذ يسككند للمتحول ‪ comparison‬السككلسككلة النصككية "‪ "less than‬وإال إذا كانت‬ ‫قيمة المتحولين متسكاوية فإنه يسند للمتحول ‪ comparison‬السلسلة النصية "‪ "equal to‬وإال‬ ‫فإنه يسند للمتحول ‪ comparison‬السلسلة النصية "‪.75 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .Convert.String‬‬ ‫‪-1‬‬ ‫في السكطر الثاني من الشكيفرة تظهر رسكالة على شكاشكة ‪ Console‬تطلب من المسكتخدم ادخال‬ ‫‪-2‬‬ ‫عدد ‪.

76 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .‫مثال إذا كانت قيمة ‪ var1‬مسكاوية لـككككككك ‪ 1‬قم بكذا وإذا كانت مساوية لـككككككك ‪ 2‬قم بكذا‪ .‬إن تنفيذ شيفرة كهذه‬ ‫باستخدام مبدأ تعشيش تعليمات ‪ if‬سيؤدي إلى شيفرة مشابهة لما يلي‪:‬‬ ‫)‪If (var1==1‬‬ ‫{‬ ‫‪// do something‬‬ ‫}‬ ‫‪Else‬‬ ‫{‬ ‫)‪If (var1==2‬‬ ‫{‬ ‫‪// do something else‬‬ ‫}‬ ‫‪Else‬‬ ‫{‬ ‫)‪If (var1==3 || var1==4‬‬ ‫{‬ ‫‪// do something else‬‬ ‫}‬ ‫‪Else‬‬ ‫{‬ ‫‪// do something else‬‬ ‫}‬ ‫}‬ ‫}‬ ‫‪.

‬‬ ‫في حالة كهذه من األفضل أن نستخدم طريقة مختلفة قليال لتحقيق هذا النوع من الشروط عندئذ من األفضل‬ ‫وضع شيفرة قسم ‪ else‬ضمن كتلة شيفرة وفي حالة كهذه سوف ننتهي ببنية من تعليمات ‪ else if‬المركبة‬ ‫كما في المثال التالي‪:‬‬ ‫)‪If (var1==1‬‬ ‫{‬ ‫‪// do something‬‬ ‫}‬ ‫)‪Else If (var1==2‬‬ ‫{‬ ‫‪// do something else‬‬ ‫}‬ ‫)‪Else If (var1==3 || var1==4‬‬ ‫{‬ ‫‪// do something els e‬‬ ‫}‬ ‫‪Else‬‬ ‫{‬ ‫‪// do something else‬‬ ‫}‬ ‫قد تظن من خالل البنية السابقة أن ‪ if…else‬تمثل شكال حديثا من تعليمة ‪ if‬إال أن ‪ if‬و‪ else‬هنا هما‬ ‫تعليمتان منفصلتان تماما والشيفرة التي كتبناها هنا هي نفسها الشيفرة السابقة إال أن األخيرة تم تنسيقها‬ ‫لتصبح أكثر قابلية للق راءة من األولى (يمكنك أن تلحظ ذلك بنفسك إذا تأملت الشيفرتين)‪. ‫مالحظة‪:‬‬ ‫من االخطاء البرمجية الشائعة كتابة الشرط الثالث في الشيفرة السابقة بالشكل ‪if‬‬ ‫)‪ (var1==3||4‬وهنا بالعودة إلى أسبقية العوامل على بعضها فإن العامل == سينفذ قبل‬ ‫العامل || والذي سيؤدي إلى تنفيذ العامل || على حد منطقي وأخر رقمي إن هذا ما سيسبب‬ ‫في حدوث خطأ باعتبار أن نتيجة الشرط في تعليمة ‪ if‬يجب أن تعيد دائما قيمة منطقية‪.‬‬ ‫‪.77 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .

‪Break‬‬ ‫}‬ ‫‪.....‪Break‬‬ ‫‪..‬ما تزال غير عملية عندما نواجه شروطا عديدة (كثالثة‬ ‫أو أربعة شروط أو أكثر) و لهذا فإن هناك تعليمة بديلة هي ‪ switch‬تمثل بنية تفرع بديلة‪. Else.‪Break‬‬ ‫‪Case < comparisonval2 >:‬‬ ‫>> ‪< Code to execute if < testvar >==< comparisonval2‬‬ ‫..‪Break‬‬ ‫‪De fault:‬‬ ‫>> ‪< Code to execute if < testvar >!=< comparisonvals‬‬ ‫.78 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ..‬‬ ‫‪Case < comparisonvalN >:‬‬ ‫>> ‪< Code to execute if < testvar > == < comparisonvalN‬‬ ‫.‫وعلى الرغم من ذلك إال أن تعليمة ‪ if….‬‬ ‫إن تعليمة ‪ switch‬مشابهة لتعليمة ‪ if‬من حيث مبدأ العمل (تنفيذها لشيفرة معينة مشروط بقيمة اختبارية‬ ‫ما) إال أن تعليمة ‪ switch‬تسمح لنا بقيم عديدة لمتحول االختبار ضمن بنية واحدة بدال من شرط واحد‬ ‫فقط (كما في تعليمة ‪ ) if‬إن هذا الشرط محدد بقيمة معينة بدال من استخدام عبارات كــ "أكبر من ‪"X‬‬ ‫وبالتالي فإن بنية تعليمة ‪ switch‬مختلفة عن بنية تعليمة ‪ if‬قليال إال أنها تمثل تقنية قوية جدا للتفرع‪.‬‬ ‫البنية االساسية لتعليمة ‪ switch‬لها الصيغة التالية‪:‬‬ ‫)> ‪Switch (< testvar‬‬ ‫{‬ ‫‪Case < comparis onval1 >:‬‬ ‫>> ‪< Code to execute if < testvar >==< comparisonval1‬‬ ‫.

‪Break‬‬ ‫‪.‬هناك‬ ‫أمر واحد يجب أن نذكره هنا وهو أنه من غير المسموح متابعة تنفيذ الشيفرة في أقسام ‪ case‬التالية بعد‬ ‫تنفيذ الشيفرة الموجودة في أحد أقسام ‪ case‬ولذا فإن التعليمة ‪ break‬هنا تقوم بإنهاء تعليمة ‪ switch‬ونقل‬ ‫التحكم للتعليمة التي تلي بنية ‪ switch‬مباشرة‪.79 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .‪Break‬‬ ‫‪…….> ‪Goto case < comparisonval2‬‬ ‫‪Case < comparisonval2 >:‬‬ ‫>> ‪< Code to execute if < testvar >== < comparisonval2‬‬ ‫.‫سيتم مقارنة القيمة في > ‪ < testvar‬مع جميع قيم > ‪( < comparisonvalN‬المحددة في تعليمات ‪)case‬‬ ‫وإن كان هناك تطابق سيتم تنفيذ الشيفرة الموجودة في القسم الذي حدث عنده التطابق وإن لم يكن هناك‬ ‫تطابق مع أية قيمة سيتم عندئذ تنفيذ الشيفرة الموجودة في القسم ‪ default‬إن كان هذا القسم موجودا‪ .‬‬ ‫هناك طرق بديلة لتجنب وصول التنفيذ من تعليمة ‪ case‬إلى تعليمة ‪ case‬التالية في لغة ‪ C#‬ويمكننا‬ ‫استخدام التعليمة ‪ return‬والتي تؤدي إلى إنهاء تنفيذ التابع الحالي بدال من مجرد الخروج من بنية ‪switch‬‬ ‫وهناك تعليمة ‪ goto‬التي شرحناها مسبقا والتي يمكننا بواسطتها نقل التحكم إلى عنوان سطر خارج بنية‬ ‫‪ switch‬الحظ أن أقسام ‪ case‬في بنية ‪ switch‬تأخذ عناوين األسطر وبناء على ذلك يمكننا نقل التحكم‬ ‫إلى تعليمة ‪ case‬أخرى باستخدام تعليمة ‪ goto‬كما في المثال التالي‪:‬‬ ‫)> ‪Switch (< testvar‬‬ ‫{‬ ‫‪Case < comparisonval1 >:‬‬ ‫>> ‪< Code to execute if < testvar >== < comparisonval1‬‬ ‫.‬‬ ‫هناك استثناء وحيد للقاعدة التي تقول إنه ال يمكن االنتقال من تنفيذ تعليمة ‪ case‬إلى تنفيذ تعليمة ‪case‬‬ ‫التالية بحرية ويقتضي ذلك بوضع تعليمات ‪ case‬مع بعضها (بتكديسها) قبل وضع كتلة من الشيفرة ونحن‬ ‫بذلك نقوم بفحص عدة شروط في وقت واحد فإن تحقق واحد من هذه الشروط ستنفذ الشيفرة الموجودة‬ ‫ضمن الكتلة على سبيل المثال‪:‬‬ ‫)> ‪Switch (< testvar‬‬ ‫{‬ ‫‪Case < comparisonval1 >:‬‬ ‫‪Case < comparisonval2 >:‬‬ ‫‪< Code to execute if < testvar >== < comparisonval1 > or‬‬ ‫>> ‪< testvar >== < comparisonval2‬‬ ‫.

‬‬ ‫يمكننا التصريح عن المتحوالت الثابتة باستخدام الكلمة المحجوزة ‪ const‬متبوعة بنوع المتحول ثم اسمه‬ ‫ومن ثم يجب إسناد قيمة له ضمن سطر التصريح مباشرة كما في المثال‪:‬‬ ‫.‪Const int intTwo‬‬ ‫.‬‬ ‫يجب أن تمثل كل مقارنة من مقارنات > ‪ < comparisonvalN‬قيمة ثابتة وأحد أبسط الطرق للقيام‬ ‫بذلك استخدام القيم الحرفية كما في المثال‪:‬‬ ‫)‪Switch (muInteger‬‬ ‫{‬ ‫‪Case 1:‬‬ ‫>‪<Code to execute if myInteger == 1‬‬ ‫.‬‬ ‫إن وضع نقطة توقف بواسطة أحد التعليمات ‪ break‬أو ‪ goto‬أو ‪ return‬يضمن وجود مسار تنفيذ نظامي‬ ‫خالل بنية ‪ switch‬في كافة الحاالت‪.‪Break‬‬ ‫}‬ ‫هناك طريقة أخرى لذلك تقتضي باستخدام المتحوال ت الثابتة ( ‪ )constant variables‬إن المتحوالت‬ ‫الثابتة هي كأي متحوالت أخرى فيما عدا أن لها ميزة واحدة فقط وهي أن القيمة التي تسند إليها عند‬ ‫التصريح عنها ال يمكن أن تتغير مطلقا للمتحوالت الثابتة فوائد عديدة في بعض المواضع كما ستجد ذلك‬ ‫خالل هذا الكتاب‪.‪Const int intTwo=2‬‬ ‫أما الشيفرة التالية فهي غير قانونية وستؤدي على حدوث خطا في الترجمة‪:‬‬ ‫.‬‬ ‫‪.‪Break‬‬ ‫‪Case -1:‬‬ ‫>‪<Code to execute if myInteger == -1‬‬ ‫‪Case default:‬‬ ‫> ‪< Code to execute if myInteger != comparisons‬‬ ‫.80 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .‪intTwo=2‬‬ ‫كذلك األمر إذا حاولنا تغيير قيمة المتحول الثابت في أي مكان من البرنامج بعد اإلسناد األولي‪.‫الحظ أن هذه الحاالت مطبقة على تعليمة ‪ default‬أيضا فليست هناك قاعدة تقول إن تعليمة ‪default‬‬ ‫يجب أن تأتي في نهاية الئحة المقارنات ويمكننا تكديسها مع تعليمات ‪ case‬إذا أردنا ذلك‪.

WriteLine("my.81 . break. } Console. name).Console switch Statement ‫ جديد باسم‬Console ‫ قم بإنشاء تطبيق‬-1 . Console.what a sexy name you have!"). case sillyName: Console. break."). case sexyName: Console.WriteLine("that's a very silly name. } ‫ ثم قم بإدخال اسم عندما يطلب منك البرنامج ثم اضغط‬Ctrl+F5 ‫ نفذ التطبيق بالضغط على مفتاح‬-3 .11( ‫الشكل‬ :‫كيفية العمل‬ How it Works: :‫في الشيفرة التي أضفناها قمنا بما يلي‬ ، sexyName،myName( ‫ في األسطر الثالثة االولى قمنا بالتصريح عن ثالث ثوابت هي‬-1 .string ‫ من النوع‬name ‫ في السطر الرابع قمن بالتصريح عن متحول باسم‬-2 .WriteLine("what is your name:"). //‫تحويل االحرف الى أحرف صغيرة و مقارنتها مع القيم المخزنة‬ switch (name. ‫ املهندس حسام الدين الرز‬:‫إعداد‬ .C# ‫ أضف الشيفرة البرمجية التالية إلى محرر نصوص‬-2 static void Main(string[] args) { //‫حجز متغير يملك قيمة ابتدائية‬ const string myName = "hussam".‫ وأسندنا لكل متغير قيمة معينة‬String ‫) من النوع‬sillyName . :switch ‫تطبيق حول استخدام تعليمة‬ . string name.WriteLine("hello {0}!".)4-11( ‫ فيظهر الشكل‬Enter )4.ReadLine(). name = Console.WriteLine("you have the same name as me!"). break. const string sexyName = "hussom".ToLower()) { case myName: Console. const string sillyName = "abo omar".

‫‪ -3‬في السطر الخامس تظهر رسالة على شاشة ‪ Console‬تسأل المستخدم عن اسمه ‪"what is‬‬ ‫"‪.‪string jop‬‬ ‫.)4-12‬‬ ‫‪.WriteLine("you are an engineer‬‬ ‫.WriteLine ("jop unknow‬‬ ‫.‪break‬‬ ‫‪default :‬‬ ‫.your name:‬‬ ‫‪ -4‬بعد إدخال المستخدم السم وضغطه على زر ‪ Enter‬يتم اسناد القيمة المدخلة للمتحول ‪.ReadLine‬‬ ‫))( ‪switch (jop.ToUpper‬‬ ‫{‬ ‫‪case "DOCTOR":‬‬ ‫.)(‪jop = Console.WriteLine("you are a doctor‬‬ ‫.‪break‬‬ ‫‪case "ENGINEER":‬‬ ‫.‬‬ ‫تطبيق أخر حول استخدام تعليمة ‪:switch‬‬ ‫‪ -1‬قم بإنشاء تطبيق ‪ Console‬جديد باسم ‪.)"!!‪Console .WriteLine("enter your jop‬‬ ‫.)"‪Console.C#‬‬ ‫)‪static void Main(string[] args‬‬ ‫{‬ ‫.("hello {0}!".82 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ . name‬‬ ‫مالحظة‪:‬‬ ‫يعمل األمر ‪ ToLower‬على تحويل حالة الحرف المدخلة إلى حالة األحرف الصغيرة وبالمثل‬ ‫هناك األمر ‪ ToUpper‬يعمل على تحويل االحرف المدخلة إلى حالة األحرف الكبيرة‪.‪break‬‬ ‫}‬ ‫}‬ ‫‪ -3‬نفذ التطبيق بالضغط على مفتاح ‪ Ctrl+F5‬ثم قم بإدخال اسم عندما يطلب منك البرنامج ثم اضغط‬ ‫‪ enter‬فيظهر الشكل (‪.)"‪Console.Console switch statement2‬‬ ‫‪ -2‬أضف الشيفرة البرمجية التالية إلى محرر نصوص ‪.)"!‪Console.ToLower‬في حالة تطابق الدخل مع إحدى القيم الثالث للثوابت السابقة تظهر رسالة‬ ‫تشير إلى تشابه االسم المدخل مع إحدى الحاالت الثالث السابقة كما تظهر رسالة ترحيب بهذا‬ ‫االسم وفي حالة عدم التشابه مع إحدى القيم السابقة سينتقل التحكم إلى خارج نطاق تعليمة ‪switch‬‬ ‫و تظهر رسالة ترحيب متبوعة باالسم المدخل )‪.name‬‬ ‫‪ -5‬أما باقي االسطر البرمجية فإن تعليمة ‪ switch‬تعمل على مقارنة قيمة دخل المستخدم مع إحدى‬ ‫الحالت الثالث للثوابت وذلك بعد تحويل النص الذي أدخله المستخدم إلى أحرف صغيرة الن‬ ‫مترجم ‪ C#‬حساس لحالة االحرف كما نوهنا سابقا ويتم هذا التحويل عبر العبارة‬ ‫)(‪ name.

)"‪Console.12‬‬ ‫سأترك لك شرح هذا البرنامج باعتقادي أن األمور واضحة‪.‪yourCount *= yearRate‬‬ ‫.‪yourCount *= yearRate‬‬ ‫.‪yourCount *= yearRate‬‬ ‫.‪yourCount *= yearRate‬‬ ‫.)"‪Console.ReadLine‬‬ ‫.‪Double yourCount.‪yourCount *= yearRate‬‬ ‫.‪yourCount *= yearRate‬‬ ‫.‪yourCount *= yearRate‬‬ ‫.WriteLine("enter rateYear:‬‬ ‫.83 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .‬‬ ‫وكمثال بسيط لنأخذ الشيفرة التالية والتي تقوم باحتساب قيمة حساب في البنك (بقيمة ابتدائية قدرها ‪1999‬‬ ‫ليرة) بعد عشر سنوات وبافتراض أن معدل الفائدة هو ‪ 1.C#‬‬ ‫)‪static void Main(string[] args‬‬ ‫{‬ ‫.‪yourCount *= yearRate‬‬ ‫.))(‪yourCount = Convert.‬‬ ‫تم ثل الحلقات المكان الذي يمكننا فيه تنفيذ الشيفرة البرمجية بصورة تكرارية إن هذه البنية مفيدة جدا وكما‬ ‫يشير اسمها فإنه يمكننا تكرار تنفيذ سطر أو كتابة كتلة برمجية ألي عدد من المرات التي نريد وبالتالي‬ ‫سنتجنب كتابة الشيفرة نفسها أكثر من مرة عندما نود تنفيذها بصورة متكررة‪.WriteLine("enter yourCount:‬‬ ‫.ToDouble(Console.)‪Console.WriteLine("yourCount after 10 years" + yourCount‬‬ ‫}‬ ‫‪.ReadLine‬‬ ‫. yearRate‬‬ ‫.ToDouble(Console.‪yourCount *= yearRate‬‬ ‫.))(‪yearRate = Convert. ‫الشكل (‪)4.‪yourCount *= yearRate‬‬ ‫.95‬أي (‪ )5%‬وهو يدفع كل سنة وليست هناك‬ ‫أية أموال تدخل أو تخرج من هذا الحساب خالل هذه المدة‪:‬‬ ‫تطبيق الحساب البنكي‪:‬‬ ‫‪ -1‬قم بإنشاء تطبيق ‪ Console‬جديد باسم ‪.Console bank‬‬ ‫‪ -2‬أضف الشيفرة البرمجية التالية إلى محرر نصوص ‪.

‫‪ -3‬نفذ التطبيق بالضغط على مفتاح ‪ Ctrl+F5‬ثم قم بإدخال قيمة الحساب ‪ yourCount‬عندما يطلب‬ ‫منك البرنامج وليكن (‪1999‬ليرة) ثم اضغط ‪ Enter‬من ثم أدخل قيمة معدل الزيادة السنوي‬ ‫‪ yearRate‬وليكن (‪ )1.84 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .ToDouble‬‬ ‫تعمل األسطر العشرة التالية على حساب قيمة الحساب بعد عشر سنوات وفقا لقيمة معدل الزيادة‬ ‫‪-3‬‬ ‫المدخل‪.‪ yourCount *= yearRate‬عشر مرات إن هذا‬ ‫االمر غير منطقي وسيسبب الكثير من التعب في حال أردنا حساب قيمة الحساب بعد ‪ 199‬سنة مثال فما‬ ‫الحل؟‬ ‫لحسن الحظ فإن نا لسنا بحاجة للقيام بذلك وإنما يمكننا وضع الشيفرة تلك ضمن حلقة تنفذ االمر السابق‬ ‫لعشر مرات أو أي عدد تكرار نريده وسوف نتعرف على بعض حلقات التكرار ضمن لغة البرمجة ‪.‬‬ ‫نالحظ في الشيفرة السابقة اننا أعدنا كتابة الشيفرة .‬‬ ‫يعمل السطر االخير على إظهار نتيجة الحساب بعد عشر سنوات‪.95‬من ثم قم بالضغط على ‪ Enter‬فيظهر الشكل (‪.Double‬‬ ‫‪-1‬‬ ‫االسطر األربعة التالية تقوم بالط لب من المستخدم إدخال قيمة الحساب "‪"enter yourCount:‬‬ ‫‪-2‬‬ ‫ومعدل الزيادة السنوي "‪ "enter rateYear:‬وتسندها للمتحوالت السابقة بعد تحويل قيم اإلدخال‬ ‫إلى النوع ‪.‬‬ ‫‪-4‬‬ ‫مالحظة‪:‬‬ ‫يعمل العامل (‪ )+‬على الجمع بين النصوص وهو بذلك يشبه عمل }{ التي كنا نستخدمها سابقا‪.C#‬‬ ‫‪.)4-13‬‬ ‫الشكل (‪)4.13‬‬ ‫كيفية العمل‪:‬‬ ‫‪How it Works:‬‬ ‫في الشيفرة التي أضفناها قمنا بما يلي‪:‬‬ ‫في السطر األول قمنا بالتصريح عن متحولين (‪ ) yearRate،yourCount‬من النوع ‪.

‪int i = 0‬‬ ‫‪do‬‬ ‫{‬ ‫.)>‪While (<test‬‬ ‫حيث يعيد التعبير >‪ <test‬قيمة منطقية‬ ‫تطبيق حول حلقة ‪:do‬‬ ‫‪ -1‬قم بإنشاء تطبيق ‪ Console‬جديد باسم ‪.‬‬ ‫الصيغة العامة لحلقة ‪ DO‬هي بالشكل التالي‪:‬‬ ‫‪Do‬‬ ‫{‬ ‫>‪<Code to be looped‬‬ ‫}‬ ‫.)‪while (i < 10‬‬ ‫‪ -3‬نفذ التطبيق بالضغط على مفتاح ‪ Ctrl+F5‬فيظهر الشكل (‪.C#‬‬ ‫.)‪Console.85 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .WriteLine("{0}".‫يتم تكرار الشيفرة ضمن حلقة ‪ DO‬بالصورة اآلتية‪ :‬ستنفذ الشيفرة الموجودة ضمن الحلقة أوال ومن ثم‬ ‫سيتم تفحص شرط منطقي فإن كانت قيمته ‪ True‬ستنفذ شيفرة الحلقة مرة أخرة وإذا كانت قيمته ‪False‬‬ ‫فسيتم الخروج من الحلقة وسينتقل التحكم لخارج الحلقة إلى السطر البرمجي التالي‪.Console do‬‬ ‫‪ -2‬أضف الشيفرة البرمجية التالية إلى محرر نصوص ‪.14‬‬ ‫‪. i++‬‬ ‫}‬ ‫.)4-14‬‬ ‫الشكل (‪)4.

86 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .‬‬ ‫.Console bank do‬‬ ‫‪ -2‬أضف الشيفرة البرمجية التالية إلى محرر نصوص ‪.))(‪yearRate = Convert.C#‬‬ ‫)‪static void Main(string[] args‬‬ ‫{‬ ‫.ToDouble(Console.95‬وعدد السنوات مساوي لـ ‪ 19‬فتظهر النتيجة كما في الشكل‬ ‫(‪.ReadLine‬‬ ‫‪do‬‬ ‫{‬ ‫.ToInt32(Console.WriteLine("enter rateYear:‬‬ ‫.WriteLine("yourCount after {0} year{1}={2}".‪yourCount *= yearRate‬‬ ‫}‬ ‫.WriteLine("enter numberYear:‬‬ ‫.)"‪Console.ToDouble(Console.do‬‬ ‫تطبيق الحساب البنكي باستخدام حلقة ‪:do‬‬ ‫‪ -1‬قم بإنشاء تطبيق ‪ Console‬جديد باسم ‪.))(‪numberYear = Convert.ReadLine‬‬ ‫.‪int numberYear. yearRate‬‬ ‫. numberYear == 1 ? "" : "s". i = 1‬‬ ‫.)"‪Console.)‪numberYear.WriteLine("enter yourCount:‬‬ ‫. yourCount‬‬ ‫}‬ ‫‪ -3‬نفذ التطبيق بالضغط على مفتاح ‪ Ctrl+F5‬ومن ثم أدخل قيمة الحساب مساوي لـ ‪ 1999‬ومعدل‬ ‫الزيادة السنوي مساوي لـ ‪ 1.)‪while (i++ < numberYear‬‬ ‫‪Console.)"‪Console. ‫كيفية العمل‪:‬‬ ‫‪How it Works:‬‬ ‫في الشيفرة التي أضفناها قمنا بما يلي‪:‬‬ ‫‪ -1‬في السطر األول قمنا بالتصريح عن متحول ‪ i‬من النوع ‪ int‬وأسندنا له قيمة أولية تساوي الصفر‪.‬‬ ‫‪ -2‬في االسطر التالية أدخلنا أمر الطباعة على شاشة ‪ Console‬ضمن حلقة ‪ do‬ليطبع لنا ناتج تغير‬ ‫العداد ‪ i++‬ذو القيمة االبتدائية ‪ 9‬إال أن أمر الطباعة حددناه بشرط وهو شرط الخروج من الحلقة‬ ‫وذلك باستخدام تعليمة ‪while‬‬ ‫لنعد إلى مثال الحساب البنكي لقد كنا نحسب قيمة الحساب بعد عشر سنوات سوف نستخدم هنا حلقة‬ ‫الحتساب قيمة الحساب بعد مرور عدد من السنوات يحدده المستخدم باستخدام حلقة ‪.ReadLine‬‬ ‫.)4-15‬‬ ‫‪.))(‪yourCount = Convert.‪Double yourCount.

‬‬ ‫‪.) ‪numberYear.‬‬ ‫‪ -4‬إن شيفرة حلقة ‪ do‬تعمل على تكرار حساب قيمة الحساب وفقا لمعدل الزيادة السنوي المدخل‬ ‫طالما أن قيمة العداد ‪ i++‬أصغر من قيمة عدد السنوات المدخل الحظ أننا هنا أدخلنا قيمة مسبقة‬ ‫للعداد تساوي ‪ 1‬أي أن العداد سوف يكرر عملية حساب الشيفرة (.yourCount‬‬ ‫أننا استخدمنا العامل الثالثي (‪ )?:‬لوضع الحرف " ‪ "s‬بعد الكلمة ‪ year‬إذا كان عدد السنوات‬ ‫ال يساوي الواحد‪.ToInt32 (Console.‪)yourCount *= yearRate‬‬ ‫تسع مرات عوضا عن عشر مرات وذلك ألننا أثناء عملية طباعة الحساب على شاشة ‪Console‬‬ ‫بعد الخروج من الحلقة سنكرر حساب الشيفرة للمرة العاشر‪.‬‬ ‫.ToDouble(Console.‬‬ ‫مالحظة‪:‬‬ ‫الحظ في الشيفرة التالية‪:‬‬ ‫‪Console.ReadLine‬‬ ‫قمنا بالطلب من المستخدم ادخال قيم المتحوالت السابقة وأسندنا قيم هذه اإلدخاالت للمتوحل‬ ‫المقابل لكل منها‪.)"‪Console.))(‪yourCount = Convert.)"‪Console. yearRate‬من النوع ‪.WriteLine ("enter rateYear:‬‬ ‫.)"‪Console.1‬‬ ‫‪ -3‬في الشيفرة التالية‪:‬‬ ‫.))(‪numberYear = Convert.))(‪yearRate = Convert.i=1‬من النوع ‪ int‬و اسندنا قيمة‬ ‫للمتحول ‪ i‬تساوي ‪.numberYear ==1?"":"s".WriteLine("enter yourCount:‬‬ ‫.ReadLine‬‬ ‫.WriteLine("yourCount after {0} year{1}={2}" .Double‬‬ ‫‪ -2‬في السطر الثاني قنا بالتصريح عن متحولين (‪ )numberYear.ReadLine‬‬ ‫.ToDouble(Console.WriteLine("enter numberYear:‬‬ ‫. ‫الشكل (‪)4.15‬‬ ‫كيفية العمل‪:‬‬ ‫‪How it Works:‬‬ ‫في الشيفرة التي أضفناها قمنا بما يلي‪:‬‬ ‫‪ -1‬في السطر األول قمنا بالتصريح عن متحولين (‪ )yourCount.87 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .

)‪Console.88 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .‪int i = 0‬‬ ‫)‪while (i < 10‬‬ ‫{‬ ‫.‫حاول أن تدخل عدد السنوات مساوي للصفر والحظ ما الذي سيحدث الشكل (‪ )4-16‬ال تستعجل في‬ ‫السؤال عن السبب فالجواب سيأتيك في الفقرة التالية‪.false‬‬ ‫للحلقة ‪ while‬الصيغة التالية‪:‬‬ ‫)>‪While (<test‬‬ ‫{‬ ‫> ‪< Code to be looped‬‬ ‫}‬ ‫مثال طباعة االعداد‪:‬‬ ‫.‬‬ ‫الشكل (‪)4.ReadLine‬‬ ‫في مثال الحساب البنكي قم باستبدال حلقة ‪ do‬بحلقة ‪ while‬كما تبين ذلك الشيفرة التالية ومن ثم أدخل‬ ‫عدد السنوات مساوي للصفر والحظ اختالف النتيجة كما يظهر في الشكل (‪:)4-17‬‬ ‫‪.WriteLine("{0}". i++‬‬ ‫}‬ ‫.)(‪Console.16‬‬ ‫حلقات ‪ while‬مشابهة لحلقات ‪ do‬إال أن هناك فرق هام بينها وهو أن التحقق من شرط االستمرار في‬ ‫حلقة ‪ do‬يتم بعد تنفيذ الشيفرة في جسم الحلقة بينما يتم التحقق من شرط االستمرار في حلقة ‪ while‬قبل‬ ‫أن ينفذ جسم الحلقة وهذا يعني أنه إذا كانت قيمة الشرط هي ‪ false‬في حلقة ‪ while‬فإن شيفرة جسم‬ ‫الحلقة لن تنفذ أبدا بعكس حلقة ‪ do‬والتي سيتم تنفيذ الشيفرة ضمنها مرة واحدة على األقل حتى إن كانت‬ ‫قيمة الشرط هي ‪.

yearRate.ReadLine()). int numberYear.ToInt32(Console.ToDouble(Console.ReadLine()). . } while (i++ < numberYear). Console. yearRate = Convert. Console. Console.‫االمثلة التي تتطلب تحققا من إدخال المستخدم في هذا الكتاب‬ :‫مالحظة‬ ‫ وذلك باستخدام‬do ‫بالطبع هناك طرق بديلة لحل هذا النوع من المشاكل باستخدام حلقة‬ :‫ االولية وذلك كما يلي‬i ‫ للتحقق من أن قيمة عدد السنوات المدخل أكبر من قيمة‬if ‫تعليمة‬ do { if (numberYear >i) yourCount *= yearRate.WriteLine("yourCount after {0} year{1}={2}" .WriteLine("enter numberYear:"). while (i++ < numberYear) { yourCount *= yearRate. yourCount = Convert.numberYear ==1?"":"s". Console. ‫ املهندس حسام الدين الرز‬:‫إعداد‬ .WriteLine("enter yourCount:").ReadLine()). } )4-17( ‫الشكل‬ ‫موضوع التحقق من إدخال المستخدم موضوع مهم جدا عند تصميم التطبيقات وسوف نجد العديد من‬ . numberYear = Convert. } Console. numberYear.WriteLine("yourCount after {0} year{1}={2}".ToDouble(Console.WriteLine("enter rateYear:").89 . static void Main(string[] args) { Double yourCount. yourCount).yourCount ). numberYear. numberYear == 1 ? "" : "s". i = 1.

< operation‬‬ ‫{‬ ‫> ‪< Code of loop‬‬ ‫}‬ ‫مثال طباعة االعداد‪:‬‬ ‫.WriteLine("{0}".)‪Console.1‬‬ ‫يجب أن تتوضع هذه المعلومات ضمن بنية الحلقة كما في الصيغة التالية‪:‬‬ ‫)> ‪For (< initialization > .‬‬ ‫‪ -2‬شرط االستمرار في تنفيذ الحلقة (وهو يعتمد على متحول الحلقة)‪.‪int i‬‬ ‫)‪for (i = 0.‬‬ ‫‪.90 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .ReadLine‬‬ ‫متحول الحلقة هنا هو متحول عددي من نوع ‪ int‬باسم ‪ i‬وله قيمة ابتدائية قدرها ‪ 9‬أي أنه يبدأ بالعد من‬ ‫القيمة ‪ 9‬وتتم زيادة قيمته مع كل دورة بمقدار ‪ 1‬إلى ان تصل قيمته إلى ‪ 9‬يقوم البرنامج السابق بطباعة‬ ‫قيمة متحول الحلقة ‪ i‬على نافذة الخرج‪.‬‬ ‫على سبيل المثال إذا أردنا أن نستخدم حلقة بعداد من ‪ 1‬إلى ‪ 19‬بحيث يخطو العداد خطوة واحدة في كل‬ ‫دورة عندئذ يجب أن يكون الشرط هو أن متحول الحلقة يجب ان يكون أقل أو يساوي ‪ 19‬والعملية التي‬ ‫ستؤدى على متحول الحلقة هي زيادة قيمته الحالية بمقدار واحد أما قيمة متحول الحلقة االبتدائية فهي ‪. i < 10.‫إن النوع األخير واألقوى من الحلقات في لغة ‪ C#‬هي حلقة ‪ for‬الحظنا أن تنفيذ حلقتي ‪ do‬و‪while‬‬ ‫اعتمد على تحقيق شرط الحلقة فقط هذا يعني أنه إذا كانت لدينا حلقة ‪ do‬طبيعة فإنها ستنفذ إلى األبد طالما‬ ‫أن الشرط محقق أما في حلقة ‪ for‬فستنفذ لعدد محدد من المرات فلهذه الحلقة عداد (يعرف بمتحول الحلقة)‬ ‫يتتبع عدد مرات تنفيذ لتعريف حلقة ‪ for‬فإننا نحتاج إلى ما يلي‪:‬‬ ‫‪ -1‬القيمة االبتدائية لمتحول الحلقة‪.‬‬ ‫‪ -3‬العملية التي ستؤدى على متحول الحلقة في نهاية كل دورة‪. i++‬‬ ‫{‬ ‫. i‬‬ ‫}‬ ‫. < condition > .)(‪Console.

‫الحظ أنه عند نهاية تنفيذ الحلقة ككل واالنتقال إلى االسطر البرمجية التالية من الشيفرة (أي عند الخروج‬ ‫من الحلقة) فإن قيمة المتحول ‪ i‬هي ‪ 19‬إن هذا يعود إلى أن الزيادة في قيمة متحول الحلقة يحدث عند‬ ‫نهاية كل دورة وقبل أن نتحقق من الشرط‪. i <= 10. i <= 10.WriteLine("HELOO WORLD‬‬ ‫. i <= 10. i++‬‬ ‫{‬ ‫.WriteLine("{0}". i++‬‬ ‫. i++‬‬ ‫.WriteLine("{0}". i‬‬ ‫}‬ ‫.)"‪Console.)‪Console. i‬‬ ‫.)‪Console.‬‬ ‫وكما في حلقة ‪ while‬فإن حلقة ‪ for‬تنفذ إذا كانت قيمة الشرط هي ‪ true‬قبل أول دورة وبالتالي ليس‬ ‫بالضرورة أن تنفذ الشيفرة ضمن جسم الحلقة دائما‪.)‪Console.ReadLine‬‬ ‫‪.WriteLine("{0}".91 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .ReadLine‬‬ ‫مالحظة‪:‬‬ ‫الحظ أننا لسنا مضطرين في هذا المثال إلى وضع تعليمة الطباعة ضمن كتلة برمجية وذلك‬ ‫ألن جسم الحلقة ال يتضمن سوى تعليمة واحدة فقط أي أنه يمكننا كتابة الشيفرة السابقة كما‬ ‫يلي‪:‬‬ ‫)‪for (int i = 1.)(‪Console.ReadLine‬‬ ‫مالحظة‪:‬‬ ‫الحظ أيضا أن أية أسطر برمجية بعد تعليمة الطباعة ال تمثل جزءا من جسم الحلقة إذا لم‬ ‫نضعها ضمن كتلة برمجية (أي ضمن األقواس "}{ ") أي أن السطر الجديد في الشيفرة‬ ‫التالية لن ينفذ ضمن الحلقة‪:‬‬ ‫)‪for (int i = 1.)(‪Console.‬‬ ‫مالحظة‪:‬‬ ‫يمكننا التصريح عن متحول الحلقة كجزء من تعليمة ‪ for‬سنعيد كتابة الشيفرة السابقة كما‬ ‫يلي‪:‬‬ ‫)‪for (int i = 1. i‬‬ ‫.)(‪Console.

WriteLine("enter an integer number:"). UInt64 i. : FOR‫تطبيق حول استخدام حلقة‬ . number =Convert .ReadLine ()). i > 0. Console.C# ‫ أضف الشيفرة البرمجية التالية إلى محرر نصوص‬-2 static void Main(string[] args) { UInt64 number.)4-18( ‫له فتظهر النتيجة كما في الشكل‬ )4. for (i = number.Console for ‫ جديد باسم‬Console ‫ قم بإنشاء تطبيق‬-1 . i++) { Console.ToUInt64 (Console . factoriel).92 . :‫مالحظة‬ :‫وإذا أردنا أن ننفذه ضمن الحلقة يجب أن نكتب كما يلي‬ for (int i = 1. i--) { factoriel = factoriel * i. Console. UInt64 factoriel=1.WriteLine("{0}". i).18( ‫الشكل‬ :‫كيفية العمل‬ How it Works: .UInt64 ‫ ) من النوع‬i،number( ‫ في السطر األول والثاني قمنا بالتصريح عن متحولين‬-1 . } ‫ ومن ثم أدخل عدد صحيح من أجل حساب قيمة العاملي‬Ctrl+F5 ‫ نفذ التطبيق بالضغط على مفتاح‬-3 . } Console. } Console.WriteLine("HELOO WORLD").ReadLine(). i <= 10. ‫ املهندس حسام الدين الرز‬:‫إعداد‬ .WriteLine("factoriel for {0}!={1}". number.

)‪Console.‪int i‬‬ ‫)‪for (i = 1.‪int i‬‬ ‫)‪for (i = 1. i--‬‬ ‫{‬ ‫.‬‬ ‫.i=6‬‬ ‫‪ -2‬األمر ‪ continue‬والذي يؤدي إلى مقاطعة دورة الحلقة الحالية واالنتقال على الدورة‬ ‫التالية على سبيل المثال‪.)(‪Console.UInt64‬‬ ‫‪ -4‬في حلقة ‪ for‬قيمة لعداد الحلقة ‪ i‬وهي قيمة دخل المستخدم وحددنا شرط للخروج من الحلقة وهو‬ ‫أن تكون قيمة ‪ i‬أكبر من الصفر وبعملية رياضية تناقصية أي عداد متناقص ومن ثم قمن بوضع‬ ‫الشيفرة البرمجية التي تقوم باحتساب قيمة العاملي ‪ factoriel‬كما في الشيفرة‪:‬‬ ‫)‪for (i = number.‫‪ -2‬في السطر الثالث قنا بالتصريح عن متحول باسم ‪ factoriel‬من النوع ‪ UInt64‬وأسندنا قيمة‬ ‫لهذا المتحول قيمة ابتدائية تساوي ‪.93 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .‪break‬‬ ‫.WriteLine("{0}". i++‬‬ ‫{‬ ‫)‪if (i == 6‬‬ ‫. i > 0.‪factoriel = factoriel * i‬‬ ‫}‬ ‫هناك أوضاع نحتاج فبها إلى التوقف عند تنفيذ جسم الحلقة قبل أن نصل إلى الحالة التي ال‬ ‫يتحقق عندها شرط الحلقة توفر لغة ‪ C#‬أربعة أوامر لذلك تعرفنا على ثالثة منها مسبقا‪:‬‬ ‫‪ -1‬األمر ‪ break‬والذي يؤدي إلى إنهاء الحلقة مباشرة واالنتقال لألسطر البرمجية التي‬ ‫تلي الحلقة‪:‬‬ ‫.))( ‪number =Convert .ReadLine‬‬ ‫ستقوم هذه الشيفرة بطباعة األرقام من ‪ 1‬إلى ‪ 5‬حيث ستنفذ تعليمة ‪ break‬عندما تصل قيمة‬ ‫‪.1‬‬ ‫‪ -3‬تعمل الشيفرة التالية‬ ‫. i <= 10. i <= 10.)"‪Console. i‬‬ ‫}‬ ‫. i++‬‬ ‫‪.ReadLine‬‬ ‫على الطلب من المستخدم إدخال عدد صحيح "‪"enter an integer number:‬ومن ثم يتم اسناد‬ ‫قيمة االدخال للمتحول ‪ number‬بعد تحويل نوع بيانات االدخال إلى النوع ‪.ToUInt64 (Console .WriteLine("enter an integer number:‬‬ ‫.

)‪Console.)(‪Console.)(‪Console.‬‬ ‫‪ -4‬األمر ‪ return‬والذي يقوم بالقفز من الحلقة ومن التابع الذي يحتويها قم بتنفيذ الشيفرة‬ ‫التالية والحظ ماذا سيحدث‪. ‫{‬ ‫)‪if (i == 6‬‬ ‫.)‪Console. i++‬‬ ‫{‬ ‫)‪if (i == 6‬‬ ‫.ReadLine‬‬ ‫حيث سوف يتم طباعة االعداد من ‪ 1‬إلى عشرة باستثناء الرقم ‪ 6‬ألنه تم مقاطعة التنفيذ عنده‪.ReadLine‬‬ ‫من الممكن أن نعرف حلقات تستمر بالتنفيذ لألبد وتسمى هذه الحلقات بالحلقات الالنهائية وأبسط حلقة‬ ‫النهائية يمكن أن نكتبها كما يلي‪:‬‬ ‫)‪While (true‬‬ ‫{‬ ‫‪// code in loop‬‬ ‫}‬ ‫إن هذا الوضع هام في بعض االحيان ويمكننا في حالة كهذه استخدام أمر مثل ‪ break‬للخروج من الحلقة‪.‬‬ ‫.WriteLine("{0}".94 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .WriteLine("{0}". i <= 10.‬‬ ‫‪ -3‬األمر ‪ goto‬والذي يسمح بالقفز إلى سطر معنون من الشيفرة وقد سبق وتناولنا هذا‬ ‫األمر‪.‬‬ ‫على كل حال عندما يحدث ذلك بسبب خطأ برمجي فإن هذا سيسبب إزعاجا بالنسبة إلينا لنأخذ الحلقة‬ ‫التالية على سبيل المثال وهي مشابهة لحلقة ‪ for‬في القسم السابق‪:‬‬ ‫‪.‪int i‬‬ ‫)‪for (i = 1.‬‬ ‫مالحظة‪ :‬إن األمر ‪ goto‬يسمح لنا بالقفز من داخل الحلقة إلى خارجها أما العكس فهو غير‬ ‫صحيح‪. i‬‬ ‫}‬ ‫. i‬‬ ‫}‬ ‫. ‪return‬‬ ‫. ‪continue‬‬ ‫.

‪int i‬‬ ‫.)‪Console.)"‪Console.‪continue‬‬ ‫.ReadLine‬‬ ‫)‪while (i <= 10‬‬ ‫{‬ ‫)‪if ((i % 2) == 0‬‬ ‫.WriteLine("inter a number‬‬ ‫.ToInt32(Console. ‫.95 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .))(‪i = Convert.WriteLine("{0}". i++‬‬ ‫}‬ ‫الحظ أن قيمة ‪ i‬لن تزيد إال عند السطر االخير من جسم الحلقة وهو ما سينفذ بعد تعليمة ‪ continue‬لكن‬ ‫عند الوصول على األمر ‪ continue‬سيتم تجاهل جميع االسطر البرمجية التالية في حسم الحلقة واالنتقال‬ ‫إلى دورة جديدة من نفس قيمة ‪ i‬السابق وباعتبار أن باقي قسمة ‪ 1‬على ‪ 2‬تساوي ‪ 9‬فإن األمر ‪continue‬‬ ‫سينفذ باستمرار دون تغيير في قيمة ‪ i‬حيث (‪ )i=1‬إن هذه الحلقة ستتسبب في تجميد النظام الحظ أنك‬ ‫تستطيع إيقاف التطبيق المجمد ب طريقة عادية ولست بحاجة إلى إعادة تشغيل الجهاز من جديد إذا حدث‬ ‫ذلك‪.‬‬ ‫‪.

‬‬ ‫‪.96 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .‬‬ ‫لقد تعرفنا في البداية على المنطق البولياني وتعرفنا على العوامل المنطقية والعوامل الخاصة بالبتات‬ ‫والمنطق البولياني هو األساس الذي ستعتمد عليه البنى التي ناقشناها بعد ذلك‪.‬‬ ‫يقيدنا التف رع في تنفيذ الشيفرة البرمجية بناء على تحقيق شرط معين وبوجود الحلقات سنتمكن من تنفيذ‬ ‫شيفرة برمجية لعدد من المرات حسب حاجتنا ورغبتنا في ذلك عندما تجد تعليمات ‪ if‬ضمن حلقات‬ ‫وحلقات ضمن حلقات ستدرك فائدة تنسيق الشيفرة بالمسافة البادئة التي تحدد لنا بداية الكتلة البرمجية‬ ‫ونهايتها فإن كتبت شيفرتك البرمجية دون جدولة الكتل ستظهر الشيفرة مربكة للغاية وان تتمكن من‬ ‫قراءتها بسهولة (على الرغم من ان تنسيق الشيفرة ال يؤثر ابدا على تنفيذها ال من قريب وال من بعيد)‪. ‫الخالصة‪:‬‬ ‫‪Summary:‬‬ ‫لقد طورنا معلوماتنا البرمجية في هذا الفصل وذلك بمناقشة بنى عديدة يمكننا استخدامها في شيفرتنا إن‬ ‫استخدام هذه البنى أمر جوهري وال بد منه عند تصميم التطبيقات في ا ية لغة برمجية وسوف نجد هذه‬ ‫البنى في معظم الشيفرة البرمجية خالل هذا الكتاب‪.

‬‬ ‫المصفوفات ( ‪ ) arrays‬وهي أنواع المتحوالت التي تحتوي على قيم عديدة من نفس النوع بحيث‬ ‫‪-3‬‬ ‫يمكن الوصول إلى هذه القيم عبر موقعها (دليلها) ضمن المصفوفة‪.‬‬ ‫الموضوع األول الذي سنتناوله هنا هو تحويل النوع (‪ )Type Conversion‬وسنتحدث هنا حول تحويل‬ ‫القيم من نوع بيانات إلى اخر لقد تعرفنا في تطبيقات سابقة على بعض أشكال التحويل إال أننا سنتناول‬ ‫تحويل النوع بتفصيل أكبر في هذا الفصل إن فهمك العميق لهذا الموضوع سيساعدك على معرفة ما‬ ‫يحدث عند خلط األنواع مع بعضها البعض ضمن التعابير والتحكم بطريقة معالجة البيانات وبالتالي تجنب‬ ‫األخطاء والمفاجئات غير السارة في الشيفرة البرمجية‪.97 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .‬‬ ‫‪-4‬‬ ‫إن أنواع البيانات هذه أكثر تعقيدا من األنواع البسيطة التي تناولناها في السابق إال أنها مفيدة جدا وتسهل‬ ‫البرمجة وتبسطها‪.‬‬ ‫البنى ( ‪ ) struts‬وهي أنواع المتحوالت المركبة والمكونة من مجموعة من أنواع المتحوالت‬ ‫‪-2‬‬ ‫األخرى‪.‬‬ ‫اللوائح ( ‪ )Lists‬وتشبه المصفوفة إلى حد ما إال أنها ديناميكية وليست ثابتة‪.‬‬ ‫لقد ذكرنا مع بداية هذا الكتاب حقيقة أن جميع البيانات بغض النظر عن نوعها تمثل بتتابع من البتات وهذه‬ ‫البتات ليست أكثر من مجرد تتابع من األصفار والواحدات إن مفهوم المتحول يأتي من كيفية تفسير‬ ‫البيانات بهذا التمثيل لتوضيح ذلك أكثر لنأخذ نوع البيانات البسيط ‪ char‬مثال يمثل هذا النوع رمزا بنظام‬ ‫تشفير ‪ Unicode‬وذلك باستخدام رقم موافق لهذا الرمز في جدول نظام التشفير وعلى الرغم من أننا‬ ‫‪. ‫الفصل الخامس‬ ‫املزيد عن املتحوالت‬ ‫لقد تعلمنا الكثير عن لغة ‪ C#‬حتى اآلن وقد حان الوقت للعودة إلى موضوع مهم تناولناه في الفصل الثالث‬ ‫أال وهو المتحوالت‪.‬‬ ‫بعد أن نغطي هذا الموضوع سنتناول أنواعا جديدة من المتحوالت‪:‬‬ ‫التعدادات ( ‪ ) enumerations‬وهي أنواع المتحوالت التي ال تقبل إال مجموعة محددة من القيم‬ ‫‪-1‬‬ ‫فقط‪.

‬‬ ‫‪ -2‬التحويل الصريح (‪ )Explicit Conversion‬حيث أن التحويل من نوع ‪ A‬إلى النوع ‪ B‬ممكن‬ ‫في حاالت معينة وأن قواعد التحويل معقدة لدرجة نحتاج فيها إلى تدخل برمجي من قبلنا قبل أن‬ ‫يتم المترجم مهمته في ذلك‪.WriteLine("sourceVar Value is:{0}".'‪char sourceVar = 'a‬‬ ‫.‪ushort destinationVar‬‬ ‫.‬‬ ‫ال تتطلب التحويالت المطلقة أي عمل من طرفنا أو أية شيفرة إضافية لنأخذ الشيفرة التالية مثال‪:‬‬ ‫.98 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ .)‪Console.destinationVar‬‬ ‫هنا سيتم اسناد قيمة المتحول ‪ sourceVar‬إلى المتحول ‪ destinationVar‬بعد ذلك سيتم طباعة قيمة‬ ‫المتحولين سيظهر الخرج كما يلي‪:‬‬ ‫‪.‪var1=var2‬‬ ‫يمكن لهذا اإلسناد أن يشتمل على تحويل مطلق وذلك إذا كان نوع المتحول ‪ var2‬قابال للتحويل المطلق‬ ‫إلى نوع المتحول ‪ var1‬ويمكن أن يكون ذلك إسناد طبيعيا دون أي تحويل لنوع المعطيات‪.WriteLine("destinationVar Value is.‬‬ ‫على كل حال لتحويل االنواع شكالن‪:‬‬ ‫‪ -1‬التحويل المطلق (‪ )Implicit Conversion‬حيث أن التحويل من النوع ‪ A‬إلى النوع ‪ B‬ممكن‬ ‫في جميع األحوال والقواعد الموافقة لهذا التحويل بسيطة لدرجة تمكننا من الوثوق بمترجم ‪C#‬‬ ‫للقيام بعملية التحويل‪.{0}".‪destinationVar =sourceVar‬‬ ‫. sourceVar‬‬ ‫.ushort‬‬ ‫هذا يعني أنه ال توجد هناك أية مشكلة من تحويل المتحوالت من نوع ‪ ushort‬إلى نوع ‪ char‬وبالعكس‬ ‫إن ذلك صحيح ولكن األمر ليس بهذه البساطة مع كل األنواع فتتابع األصفار والواحدات لنوع متحول ما‬ ‫ليس بالضرورة أن يشير إلى ذا ته للتابع نفسه من األصفار والواحدات لنوع آخر من المتحوالت‪.) ‪Console.‫نتعامل مع قيم من هذا النوع على شكل رمز ما مثل "‪ "a‬إال أن تخزين هذا الرمز يكون على هيئة قيمة‬ ‫رقمية من نوع ‪.‬‬ ‫لنأخذ مثاال يصف ل نا التحويل المطلق‪:‬‬ ‫لقد ذكرنا في البداية أن النوعين ‪ ushort‬و‪ char‬هما نوعان مرتبطان ببعضهما لدرجة كبيرة فكالهما‬ ‫يخزن القيم من ‪ 0‬إلى ‪ 65535‬يمكننا تحويل القيم بين هذين النوعين بشكل مطلق كما في الشيفرة التالية‪:‬‬ ‫.

99 -‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ . float . float . decimal‬‬ ‫‪Int‬‬ ‫‪long . ulong .1‬‬ ‫على الرغم من أن كال المتحولين يحتفظان بالمعلومات نفسها إال أن لكل متحول تفسيرا مختلفا للمعلومات‬ ‫المخزنة ضمنه بحسب نوعه‪. ushort . float . decimal‬‬ ‫‪Long‬‬ ‫‪float . double . float . float . decimal‬‬ ‫‪Ulong‬‬ ‫‪double‬‬ ‫‪Float‬‬ ‫‪ushort . long . float . int . double . long .‬‬ ‫هناك الكثير من التحويالت المطلقة لألنواع البسيطة ولكن ليس للنوعين ‪ bool‬و‪ string‬أية تحويالت‬ ‫مطلقة يبين الجدول التالي إمكانيات التحويالت المطلقة لألنواع الرقمية (أي التي يمكن للمترجم التكفل‬ ‫بعمليات التحويل تلك)‪:‬‬ ‫األنواع‬ ‫النوع‬ ‫‪Short . double . long. uint . decimal‬‬ ‫‪Byte‬‬ ‫‪Short . decimal‬‬ ‫‪Sbyte‬‬ ‫‪int. decimal‬‬ ‫‪Short‬‬ ‫‪int . int . ulong . decimal‬‬ ‫‪Ushort‬‬ ‫‪long. long . uint . double .‬‬ ‫على كل حال قد تقول إن المشكلة التي نتحدث عنها هنا ليست بالضرورة أن تحدث فإذا كنت تعلم أن قيمة‬ ‫المتحول من نوع ‪ short‬لن تزيد عن ‪ 255‬فإنك ستتمكن من تحويل المتحول على النوع ‪ byte‬صحيح؟‬ ‫‪. decimal‬‬ ‫‪char‬‬ ‫ال تقلق فأنت لست بحاجة إلى حفظ هذا الجدول لكي تتمكن من معرفة األنواع التي يمكنك استخدام التحويل‬ ‫المطلق بين قيم متحوالتها لكن هناك أمر يجدر بك أن تالحظه من خالل هذا الجدول وهو أن مجال قيم‬ ‫األنواع التي يمكنك التحويل إليها يجب أن يالئم مجال قيم النوع الذي ستحوله ويمكننا أن نستخلص قاعدة‬ ‫للتحويل المطلق كما يلي‪ :‬ألي نوع ‪ A‬فإنه يمكننا تحويله تحويال مطلقا إلى نوع أخر ‪ B‬وذلك إذا أمكننا‬ ‫تمثيل جميع القيم الممكن تمثيلها في النوع ‪ A‬ضمن النوع ‪. double . long . ‫الشكل (‪)5.B‬‬ ‫إن هذا منطقي جدا فإذا حاولنا أن نسند قيمة إلى متحول يقع خارج مجال نوع ذلك المتحول فإن هذا‬ ‫سيتسبب في مشكلة على سبيل المثال يستطيع النوع ‪ short‬أن يحفظ القيم من ‪ 9‬إلى ‪ 32767‬أما النوع‬ ‫‪ byte‬فإن أقصى قيمة يمكنه حفظها هي ‪ 255‬وبالتالي سوف نواجه مشكلة حقيقية عند تحويل قيمة من‬ ‫نوع ‪ short‬إلى نوع ‪ byte‬فإن كانت تلك القيمة واقعة بين ‪ 256‬و‪ 32767‬فسوف لن يتمكن النوع ‪byte‬‬ ‫من استيعاب هذه القيمة ألنها تقع خارج مجاله‪. double . ulong . double . ulong . double . decimal‬‬ ‫‪Uint‬‬ ‫‪float . uint . float . double . int .

‪destinationVar =sourceVar‬‬ ‫.‬‬ ‫لكي نستطيع ترجمة هذه الشيفرة يجب أن نظيف عبارة برمجية للقيام بالتحويل الصريح والطريقة األبسط‬ ‫للقيام بذلك في هذا السياق تقضي بتشكيل (‪ )cast‬متحول ‪ short‬ضمن متحول ‪ byte‬إن ما نقصده بالتشكيل‬ ‫‪ casting‬هو تحويل البيانات من نوع ألخر بصورة قسرية ويأخذ هذا التحويل الصيغة التالية‪:‬‬ ‫‪(destinationType) sourceVar‬‬ ‫حيث سيتم تحويل المتحول ‪ sourceVar‬إلى النوع ‪.{0}". sourceVar‬‬ ‫.‪short sourceVar = 8‬‬ ‫.‫إن ابسط جواب لهذا السؤال هو بالتأكيد يمكنك ذلك إال أن الجواب االكثر تحديدا هو أنك تستطيع ذلك‬ ‫ولكن بواسطة التحويل الصريح (‪ )Explicit Conversion‬إن التحويل الصريح لألنواع مشابه لقولنا‪:‬‬ ‫"حسنا أنا أعلم أنك حذرتني من القيام بذلك إال أنني سأتحمل مسؤولية ما سيحدث"‪.‪byte destinationVar‬‬ ‫.)‪Console.destinationType‬‬ ‫مالحظة‪:‬‬ ‫الحظ أن تطبيق هذه الصيغة محصور في حاالت محددة فاألنواع التي ليست بينها أية عالقات‬ ‫ال يمكننا استخدام التشكيل (‪ )casting conversion‬معها‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪100 -‬‬ ‫‪-‬‬ .WriteLine("destinationVar Value is.‬‬ ‫على سبيل المثال سنقوم بتعديل الشيفرة السابقة إلى الشيفرة التالية بهدف إجراء تحويل من النوع ‪short‬‬ ‫إلى ‪:byte‬‬ ‫. An explicit conversion exists‬‬ ‫لحسن الحظ فإن مترجم ‪ C#‬ذكي لدرجة يستطيع فيها كشف التحويالت الصريحة المفقودة‪.WriteLine("sourceVar Value is:{0}".‬‬ ‫وكما يشير االسم فإن هذه التحويالت ال تحدث إال عندما نطلب من المترجم تحويل القيمة من نوع إلى‬ ‫آخر بصراحة وبسبب ذلك فإن هذا النوع من التحويالت يتطلب شيفرة إضافية كما وأن هذه الشيفرة تختلف‬ ‫من حالة ألخرى وذلك بسبب منهجية التحويل ولكن قبل أن نتعرض ألية شيفرة تحويل صريح لنلق نظرة‬ ‫على ما سيحدث عندما ال نستخدم التحويل الصريح‪.) ‪Console.destinationVar‬‬ ‫إذا حاولنا ترجمة هذه الشيفرة فسوف نستقبل الخطأ التالي‪:‬‬ ‫‪Cannot implicitly convert type 'short' to 'byte'.

‫وبناء على ذلك يمكننا أن نعدل المثال السابق باستخدام صيغة التشكيل التي تجبر على التحويل من ‪short‬‬ ‫إلى ‪ byte‬كما يلي‪:‬‬ ‫.destinationVar‬‬ ‫والنتيجة هي كما في الشكل (‪:)5-3‬‬ ‫الشكل (‪)5.‪short sourceVar = 259‬‬ ‫.WriteLine("sourceVar Value is:{0}".) ‪Console. sourceVar‬‬ ‫.2‬‬ ‫حسنا ماذا سيحدث عندما نحاول اسناد التحويل الصريح مع قيمة ال تتسع ضمن مجال النوع المراد التحويل‬ ‫إليه؟! الشيفرة التالية توضح ذلك‪:‬‬ ‫.)‪Console.‪destinationVar =(byte)sourceVar‬‬ ‫.3‬‬ ‫ماذا حدث؟ إن ما قمنا به هنا هو محاولة إسناد القيمة ‪ 259‬إلى متحول من نوع ‪ byte‬وهو نوع ال يمكن‬ ‫أن يتقبل قيما أكبر من ‪ 255‬لكن نتيجة التحويل الصريح ظهرت غريبة نوعا ما حسنا لنلق نظرة على‬ ‫التمث يل الثنائي لهذين الرقمين باإلضافة إلى أقصى قيمة لنوع المعطيات ‪:byte‬‬ ‫‪259=100000011‬‬ ‫‪3=000000011‬‬ ‫يمكننا أن نرى ان ما حدث هنا هو فقدان البتات في الطرف االيسر من القيمة ‪ 259‬إن ما حدث هنا هو‬ ‫محاولة لتخزين القيمة ‪ 259‬ضمن حيز النوع ‪ byte‬وحسب تعريف النوع ‪ byte‬فإن أكبر قيمة يمكنه‬ ‫استيعابها هي ‪ 255‬والتي تمثل بثماني بتات بالمقارنة مع القيمة ‪ 259‬والتي تمثل بتسع بتات وبناء على‬ ‫ذلك سيتم إهمال جميع البتات في أقصى اليسار الواقعة خارج مجال النوع ‪ byte‬وهي بت واحد فقط في‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪101 -‬‬ ‫‪-‬‬ .‪byte destinationVar‬‬ ‫.{0}".WriteLine("sourceVar Value is:{0}".‪byte destinationVar‬‬ ‫. sourceVar‬‬ ‫.WriteLine("destinationVar Value is.WriteLine("destinationVar Value is.) ‪Console.)‪Console.destinationVar‬‬ ‫والذي سينتج عنه الخرج كما في الشكل (‪:)5-2‬‬ ‫الشكل (‪)5.‪destinationVar =(byte)sourceVar‬‬ ‫.{0}".‪short sourceVar = 8‬‬ ‫.

‫حالتنا هنا إن حدوث تحويل كهذا يمكن أن يؤدي إلى أخطاء جسيمة جدا (تخيل حدوث مثل هذه الهفوات‬ ‫في برنامج محاسبة)‪.WriteLine("sourceVar Value is:{0}". sourceVar‬‬ ‫.‪byte destinationVar‬‬ ‫.{0}".)‪destinationVar =checked ((byte)sourceVar‬‬ ‫.destinationVar‬‬ ‫عند تنفيذ الشيفرة ستظهر رسالة خطأ كما في الشكل (‪ )5-4‬والتي تخبرنا بوجود حالة طفحان‪.)‪Console.‬‬ ‫الشكل (‪)5.WriteLine("destinationVar Value is.‪short sourceVar = 259‬‬ ‫.) ‪Console.‬‬ ‫هناك كلمتان مفتاحيتان إلعداد ما نسميه بسياق تفحص الطفحان (‪)overflow checking context‬‬ ‫لتعبير ما وهما ‪ checked‬و ‪ unchecked‬يمكننا استخدام هاتين الكلمتين بالصورة التالية‪:‬‬ ‫)‪Checked (expression‬‬ ‫)‪Unchecked (expression‬‬ ‫وبالتالي يمكننا تفحص الطفحان في المثال السابق كما يلي‪:‬‬ ‫.‬‬ ‫لكي نتجنب الوقوع في هفوات كهذه علينا تفحص قيمة المصدر ومقارنتها مع حدود المتحول الهدف‬ ‫المعلومة سوف نتعلم كيفية القيام بذلك في الفصل القادم عندما نتناول منطق التطبيق والتحكم في سير‬ ‫التنفيذ على كل حال هناك تقنيات أخرى يمكننا االستفادة منها هنا حيث سنستخدمها لتنبيه النظام حول‬ ‫إمكانية التحويل الصريح القسري في زمن التنفيذ ألشكال كهذه من التحويالت وتعتمد هذه التقنية على‬ ‫تفحص ما يعرف بحالة الطفحان (‪ )overflow‬حيث أن أية محاولة لوضع قيمة ضمن متحول ال يمكنه‬ ‫استيعابها ستؤدي إلى حدوث حالة الطفحان‪.4‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪102 -‬‬ ‫‪-‬‬ .

WriteLine("enter the number‬‬ ‫.‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪103 -‬‬ ‫‪-‬‬ .‫واآلن إذا استبدلنا الكلمة ‪ checked‬بالكلمة ‪ unchecked‬في هذه الشيفرة فسوف نحصل على النتيجة‬ ‫التي حصلنا عل يها في السابق وهو مطابق للسلوك االفتراضي عند عدم وضع أي كلمة‪.)‪Console.ReadLine‬‬ ‫.‬‬ ‫على سبيل المثال‪ :‬إذا حاولت تحويل سلسلة نصية مثل "‪ "Number‬إلى قيمة من نوع ‪ double‬باستخدام‬ ‫األمر )(‪ Convert.‬‬ ‫إن نمط التحويل الصريح الذي استخدمناه في تطبيقاتنا السابقة في هذا الكتاب مختلف قليال عما تعلمناه‬ ‫عن التحويل الصريح حتى اآلن في هذا الفصل لقد قمنا في السابق بتحويل السالسل النصية إلى أرقام‬ ‫باستخدام أوامر مثل )(‪ Convert.))(‪a = Convert.ToDouble‬كما في الشيفرة التالية فإن ذلك سوف يؤدي أثناء التنفيذ لظهور رسالة‬ ‫الخطأ كما في الشكل (‪.ToDouble‬وهو أمر ال يمكن تطبيقه على أي سلسلة نصية‪.)"‪Console.)5-5‬‬ ‫.‪Double a‬‬ ‫.ToDouble(Console.WriteLine(a‬‬ ‫الشكل (‪)5-5‬‬ ‫وكما ترى هنا فإن العملية ستخفق وهذا شيء طبيعي ولكي تنجح عملية تحويل كهذه يجب أن تمثل السلسلة‬ ‫النصية تمثيال شرعيا رقميا ويجب أال يتسبب هذا الرقم بحالة طفحان‪.

To Single(val‬‬ ‫تحويل قيمة ‪ val‬إلى النوع ‪String‬‬ ‫)‪Convert.To Double(val‬‬ ‫تحويل قيمة ‪ val‬إلى النوع ‪Short‬‬ ‫)‪Convert.To Byte (val‬‬ ‫تحويل قيمة ‪ val‬إلى النوع ‪char‬‬ ‫)‪Convert.C#‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪104 -‬‬ ‫‪-‬‬ .To Char (val‬‬ ‫تحويل قيمة ‪ val‬إلى النوع ‪decimal‬‬ ‫)‪Convert.To Int64(val‬‬ ‫تحويل قيمة ‪ val‬إلى النوع ‪SByte‬‬ ‫)‪Convert.To Decimal(val‬‬ ‫تحويل قيمة ‪ val‬إلى النوع ‪double‬‬ ‫)‪Convert.To Int32(val‬‬ ‫تحويل قيمة ‪ val‬إلى النوع ‪Long‬‬ ‫)‪Convert.NET‬وليست جزءا من لغة ‪.ToBoolean(val‬‬ ‫تحويل قيمة ‪ val‬إلى النوع ‪byte‬‬ ‫)‪Convert.To String (val‬‬ ‫تحويل قيمة ‪ val‬إلى النوع ‪UShort‬‬ ‫)‪Convert. ‫مالحظة‪:‬‬ ‫نقصد بالتمثيل الشرعي الرقمي هو أن تتضمن السلسلة النصية عالمة اختيارية (سواء‬ ‫كانت – أو ‪ )+‬متبوعة بعدد من األرقام ومن ثم متبوعة بفاصلة اختيارية متبوعة بعدد من‬ ‫األرقام متبوعة برمز " ‪ "e‬أو "‪ " E‬اختياري ثم متبوعة بعالمة (‪ +‬أو ‪ )-‬اختيارية متبوعة‬ ‫بعدد من األرقام وال شيء سوى ذلك عدا وجود الفراغات (قبل وبعد هذا التتابع وليس‬ ‫ضمنه) باستخدامنا لجميع هذه األمور االختيارية يمكننا أن نكتب سلسلة نصية بالشكل‬ ‫‪ -5.To Int16(val‬‬ ‫تحويل قيمة ‪ val‬إلى النوع ‪Int‬‬ ‫)‪Convert.‬‬ ‫هناك العديد من التحويالت الصريحة التي يمكننا تطبيقها بهذه الطريقة على سبيل المثال‪:‬‬ ‫النتيجة‬ ‫التحويل‬ ‫تحويل قيمة ‪ val‬إلى النوع ‪bool‬‬ ‫)‪Convert.ToInt32‬يعود ذلك إلى أن هذه‬ ‫األوامر تمثل جزءا من إطار عمل ‪ . To UInt32 (val‬‬ ‫مالحظة‪:‬‬ ‫الحظ أن أسماء بعض أوامر التحويل مختلفة عن أسماء األنواع في ‪ C#‬فعلى سبيل المثال‬ ‫لتحويل قيمة ما إلى النوع ‪ int‬سنستخدم األمر ‪ Convert.To UInt16(val‬‬ ‫تحويل قيمة ‪ val‬إلى النوع ‪ULong‬‬ ‫)‪Convert.39594846161‬ومعاملتها كقيمة رقمية‪.To SByte(val‬‬ ‫تحويل قيمة ‪ val‬إلى النوع ‪Float‬‬ ‫)‪Convert.

‫لنلق نظرة على مثال يغطي العديد من أنواع التحويالت التي تحدثنا عنها في هذا القسم‬ :‫تطبيق حول تحويالت األنواع‬ .->short:{0}*{1}->{2}" .‫إن ما يجب اإلشارة إليه هنا هو أن هذه األوامر تتفحص حالة الطفحان دائما وبالتالي فإن الكلمتين‬ . shortval = 4. longresult = integerval + Convert. stringval.ToString(boolval) + Convert. long longresult.->long:{0}+{1}->{2}" .999.)5-6( ‫ فيظهر الشكل‬Ctrl+F5 ‫ نفذ التطبيق بالضغط على مفتاح‬-6 )5. Console. int integerval = 67. longresult).WriteLine("implicet.WriteLine("explicit. Console. shortval. doubleresult). doubleval. stringresult = Convert.6( ‫الشكل‬ :‫كيفية العمل‬ How it Works: ‫ املهندس حسام الدين الرز‬:‫إعداد‬ 105 - - .->short:{0}->{1}". double doubleresult. stringval = "17". bool boolval = true.WriteLine("mixed. float floatval = 10. Console.ToString(doubleval).5F.WriteLine("explicit. stringresult). shortresult). boolval. } . integerval. Console.‫ وإعدادات المشروع ال تؤثر على هذه األوامر‬unchecked ‫ و‬checked .->string:\"{0}\"+\"{1}\"->{2}" . shortresult = (short)floatval. doubleval = 99.ToInt64(stringval).C# ‫ أضف الشيفرة البرمجية التالية إلى محرر نصوص‬-5 static void Main(string[] args) { short shortresult.Console Convert Commands ‫ جديد باسم‬Console ‫ قم بإنشاء تطبيق‬-4 . floatval. string stringresult.WriteLine("variabel conversion exampel\n"). floatval. Console. doubleresult = floatval * shortval.

)‪doubleResult = floatval + (floatval * shortval‬‬ ‫إن العمل الذي سينفذ هنا أوال هو * وهذا سيؤدي إلى تحويل القيمة ‪ shortval‬إلى النوع ‪ float‬بعد ذلك‬ ‫ستتم معالجة العامل ‪ +‬والذي ال يتطلب أية عملية تحويل باعتبار أن حدي العامل هما هنا من نوع ‪float‬‬ ‫(المتحول ‪ floatval‬وقيمة ‪ float‬الناتجة من التعبير‪ ) floatval * shortval‬وأخيرا فإن حاصل التعبير‬ ‫الناتج من نوع ‪ float‬سيحول إلى النوع ‪ double‬وذلك عند اسناد قيمة ‪ float‬إلى متحول من نوع‬ ‫‪( double‬وهو المتحول ‪.‪doubleResult = (short)floatval * shortval‬‬ ‫يتم تطبيق التحويالت الصريحة لألنواع بواسطة صيغ التشكيل كما في السطر السابق وتأخذ صيغة‬ ‫التشكيل األولوية نفسها التي تأخذها العوامل األحادية مثل ‪( ++‬عند استخدامها كبادئة) أي أن لها األسبقية‬ ‫األعلى دونا عن جميع العوامل األخرى‪.)doubleResult‬‬ ‫يظهر هذا النوع من التحويالت معقدا من الوهلة األولى إال أنه عندما نقوم بتجزئة التعبير إلى عدة أجزاء‬ ‫سنتمكن من تحديد عمليات التحويل الحاصلة بناء على أولوية العوامل‪.‬‬ ‫مالحظة‪:‬‬ ‫إن هذا ال يعني بالضرورة أن تكون النتيجة من نوع ‪ short‬وبما أن حاصل عملية ضرب‬ ‫قيمتين من نوع ‪ short‬يمكن أن تتجاوز مجال النوع ‪ short‬فإن هذا النوع من العمليات‬ ‫سيعيد قيمة من نوع ‪ int‬بصورة افتراضية‪.‫يتضمن هذا المثال جميع أنواع التحويالت كما ترى ضمن الشيفرة وذلك ضمن عمليات إسناد وتعابير‬ ‫بسيطة شرحناها مسبقا لنبدأ بتناول هذه الشيفرة خطوة بخطوة‪:‬‬ ‫.float‬‬ ‫ويمكن نا أن نتجاوز هذا السلوك بحيث نكتب‪:‬‬ ‫.‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪106 -‬‬ ‫‪-‬‬ .‬‬ ‫وعندما نواجه تعابيرا تتضمن أنواع مختلفة فإن التحويالت تحدث مع كل عامل يعالج أوال وذلك بحسب‬ ‫أولوية تلك العوامل أي أن‪:‬‬ ‫.‪doubleResult = floatval * shortval‬‬ ‫لقد قمنا هنا بضرب قيمة من نوع ‪ short‬بقيمة من نوع ‪ float‬وفي حالة كهذه حيث لم نحدد فيها تحويال‬ ‫صريحا فإنه سيتم استخدام التحويل المطلق متى أمكن ذلك والتحويل المطلق المعقول في السطر السابق‬ ‫هو تحويل القيمة من نوع ‪ short‬إلى ‪.

‬‬ ‫‪-2‬‬ ‫المصفوفات‪.‫لقد تناولنا حتى اآلن جميع األنواع البسيطة المتوفرة في ‪ C#‬تتضمن لغة ‪ C#‬ثالثة أنواع معقدة للمتحوالت‬ ‫لكنها مفيدة جدا وهي‪:‬‬ ‫التعدادات أو مجموعات القيم‪.‬‬ ‫‪-3‬‬ ‫اللوائح‬ ‫‪-4‬‬ ‫الشكل التالي يبين أنواع البيانات المستخدمة في ‪.‬‬ ‫‪-1‬‬ ‫البنى‪.C#‬‬ ‫‪Variable Types‬‬ ‫‪Simple‬‬ ‫‪Enumeration‬‬ ‫‪Structur‬‬ ‫‪Array‬‬ ‫‪Lists‬‬ ‫‪Floating‬‬ ‫‪Integral‬‬ ‫‪Chr‬‬ ‫‪bool‬‬ ‫‪Decimal‬‬ ‫‪point‬‬ ‫‪Byte‬‬ ‫‪Fl oat‬‬ ‫‪SByte‬‬ ‫‪Double‬‬ ‫‪Long‬‬ ‫‪ULog‬‬ ‫‪Short‬‬ ‫‪UShort‬‬ ‫‪i nt‬‬ ‫‪Ui nt‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪107 -‬‬ ‫‪-‬‬ .

‬‬ ‫……‬ ‫‪ValueN.‬‬ ‫تعرف التعدادات بواسطة الكلمة ‪ enum‬كما في الصيغة التالية‪:‬‬ ‫‪enum typeName‬‬ ‫{‬ ‫‪Value1..‫إن جم يع األنواع التي تناولناها إلى اآلن (عدا النوع ‪ )string‬لها مجموعة محددة من القيم المسموح بها‬ ‫وهو ما سميناه بمجال قيم النوع إن هذا المجال كبير جدا ومتصل في أنواع مثل ‪ double‬نقصد بالمجال‬ ‫المتصل أنه من أجل قيمتين قريبتين جدا من بعضهما في هذا المجال فإن هناك قيمة تقع بين هاتين القيمتين‬ ‫إن أبسط هذه األنواع هو ‪ bool‬والذي ال يتقبل سوى قيمتين فقط‪ true :‬أو ‪.west ،east‬‬ ‫في حاالت كهذه يكون استخدام التعدادات هو الحل المثالي تمكننا التعدادات من صنع أنواع جديدة مثل‬ ‫النوع ‪ orientation‬مثال فهي تسمح لنا بتعريف نوع جديد يتقبل عددا منهيا من القيم التي يمكن أن تأخذها‬ ‫المتحوالت التي تنتمي لهذا النوع‪.‬‬ ‫}‬ ‫يمكننا بعد ذلك التصريح عن المتحوالت لهذا النوع الجديد بالطريقة االعتيادية‪:‬‬ ‫.‬‬ ‫‪Value2.value‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪108 -‬‬ ‫‪-‬‬ .‬‬ ‫ما نحتاجه للقيام بذلك هو إنشاء نوع جديد باسم ‪ orientation‬يتضمن القيم األربعة الممكنة السابقة أي‬ ‫أن علينا تعريف النوع الجديد أوال ومن ثم نستطيع استخدامه مع متحوالتنا‪.‪typeName varName‬‬ ‫وإسناد القيم إلى هذا المتحول كما يلي‪:‬‬ ‫.‪varName=typeName..false‬‬ ‫هناك الكثير من الحاالت التي نحتاج فيها إلى تعريف متحول ال يتقبل إال مجموعة ثابتة من القيم على‬ ‫سبيل المثال يمكن أن يكون لدينا النوع ‪ orientation‬مثال والذي يستطيع تخزين القيم ‪،south ،north‬‬ ‫‪.

Byte .... ulong . Value2.‬‬ ‫‪.‫وللتعدادات نوع تحتي (‪ ) underlying type‬وهو نوع القيم في التعداد فكل قيمة في التعداد يمكن أن‬ ‫تخزن على شكل قيمة لهذا النوع التحتي إن النوع االفتراضي هو ‪ int‬ويمكننا أن نحدد نوعا آخر باستخدام‬ ‫التصريح التالي‪:‬‬ ‫‪enum typeName : underlyingType‬‬ ‫{‬ ‫‪Value1. uint ..‬‬ ‫‪ValueN=actualValN‬‬ ‫}‬ ‫وباإلضافة لذلك يمكن أن تأخذ ‪ . long ..‬‬ ‫‪ValueN‬‬ ‫}‬ ‫يمكن أن تأخذ التعدادات األنواع التحتية التالية‪:‬‬ ‫‪Short .....‬‬ ‫‪Value2. ushort . Value1‬قيما متشابهة كما يلي‪:‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪109 -‬‬ ‫‪-‬‬ . int ..‬‬ ‫‪Value2=actualVal2.... Sbyte‬‬ ‫إن كل قيمة موجودة ضمن التعداد تقابل قيمة من النوع التحتي ويتم ذلك وفقا لترتيب توضع القيم ضمن‬ ‫التعداد بدا من الصفر هذا يعني أن للقيمة ‪ value1‬القيمة ‪ 9‬وفقا للنوع التحتي والقيمة ‪ value2‬لها القيمة‬ ‫‪ 1‬وفقا للنوع التحتي وهكذا يمكننا أن نتجاوز ذلك وأن نضع قيما من عندنا وذلك باستخدام عامل االسناد‬ ‫كما يلي‪:‬‬ ‫‪enum typeName : underlyingType‬‬ ‫{‬ ‫‪Value1=actualVal1.‬‬ ‫‪Value3.‬‬ ‫‪..

...‬‬ ‫‪Value4‬‬ ‫‪..‬‬ ‫}‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪110 -‬‬ ‫‪-‬‬ .‬‬ ‫‪ValueN=actualValN‬‬ ‫}‬ ‫تحذير‪:‬‬ ‫ال يمكننا إسناد القيم بصورة تعاوديه دائرية كما في الشيفرة‪:‬‬ ‫‪enum typeName : underlyingType‬‬ ‫{‬ ‫‪Value1= Value2.‬‬ ‫‪.. ‫‪enum typeName : underlyingType‬‬ ‫{‬ ‫‪Value1=actualVal1.‬‬ ‫‪Value3..‬‬ ‫‪Value2= Value1...‬‬ ‫‪Value2..‬‬ ‫‪ValueN=actualValN‬‬ ‫}‬ ‫الحظ أننا هنا لم نحدد قيمة صريحة لـ ‪ Value3‬و بالتالي ستأخذ قيمة تلقائية من النوع التحتي وتلك القيمة‬ ‫هي آخر قيمة تم تحديدها بصورة صريحة مضافا إليها واحد على سبيل المثال ستأخذ القيمة ‪Value4‬‬ ‫نفس قيمة ‪:Value2‬‬ ‫‪enum typeName : underlyingType‬‬ ‫{‬ ‫‪Value1=actualVal1.‬‬ ‫‪Value3= Value1..‬‬ ‫‪Value2= Value1.

WriteLine ("mydirection="+mydirection). west = 4 } class Program { static void Main(string[] args) { byte directionByte.Console Enumeration ‫ جديد باسم‬Console ‫ قم بإنشاء تطبيق‬-1 .)5-7( ‫ فيظهر الشكل‬Ctrl+F5 ‫ نفذ التطبيق بالضغط على مفتاح‬-3 )5. west = 4 } class Program { static void Main(string[] args) { orientation mydirection = orientation. south = 2. orientation myDirection = orientation. } } } .7( ‫الشكل‬ :‫ اخرج من التط بيق وقم بتعديل الشيفرة كما يلي‬-4 namespace Console_Enumeration { enum orientation : byte { north = 1. south = 2.south. east = 3. east = 3. Console .south.C# ‫ أضف الشيفرة البرمجية التالية إلى محرر نصوص‬-2 namespace Console_Enumeration { enum orientation : byte { north = 1. . ‫ املهندس حسام الدين الرز‬:‫إعداد‬ 111 - - . string directionString.‫حيث سيتسبب ذلك في حدوث خطأ‬ :‫تطبيق حول التعدادات‬ .

)‪Console. ‫.)5-8‬‬ ‫الشكل (‪)5. directionString‬‬ ‫}‬ ‫}‬ ‫}‬ ‫‪ -5‬نفذ التطبيق بالضغط على مفتاح ‪ Ctrl+F5‬فيظهر الشكل (‪.WriteLine("byte equivalent={0}".) ‪Console.‪directionByte = (byte)myDirection‬‬ ‫علينا استخدام التحويل الصريح ذاته إذا عكسنا الوضع فإذا أردنا تحويل قيمة من نوع ‪ byte‬إلى‬ ‫‪ orientation‬فإننا سنستخدم التشكيل ‪ orientation‬فعلى سبيل المثال إذا كان لدينا متحول من نوع ‪byte‬‬ ‫باسم ‪ myByte‬وأردنا تحويل قيمته إلى النوع ‪ orientation‬وإسناد القيمة الناتجة إلى المتحول‬ ‫‪ myDirection‬فإننا سنكتب‪:‬‬ ‫.‬‬ ‫أما في المرحلة التالية فقد عدلنا الشيفرة بهدف تحويل قيمة المتحول من نوع ‪ orientation‬إلى النوع‬ ‫‪ byte‬الحظ أن علينا استخدام التحويل الصريح هنا فعلى الرغم من أن النوع التحتي للنوع ‪orientation‬‬ ‫هو ‪ byte‬إال أنه مازلنا نحتاج الستخدام التشكيل ‪ byte‬كي نتمكن من تحويل قيمة ‪ myDirection‬إلى‬ ‫النوع ‪.‪directionByte = (byte)myDirection‬‬ ‫. directionByte‬‬ ‫.‬‬ ‫يستعرض هذا المثال أساسيات تعودنا على رؤيتها في الفصول السابقة فلقد استعرض الطريقة األساسية‬ ‫إلنشاء متحول لنوع البيانات الجديد وإسناد قيمة لهذا المتحول ومن ثم إخراج قيمة المتحول على الخرج‪.WriteLine ("mydirection="+myDirection‬‬ ‫.‪myDirection = (orientation)myByte‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪112 -‬‬ ‫‪-‬‬ .)‪directionString = Convert.)‪Console .8‬‬ ‫كيفية العمل‪:‬‬ ‫‪How it Works:‬‬ ‫لقد قمنا هنا بتعريف نوع تعداد جديد باسم ‪ orientation‬إن أول ما نالحظه حول هذه الشيفرة هو أن‬ ‫تعريف النوع الجديد موجود ضمن فضاء األسماء مباشرة وليس ضمن باقي الشيفرة يعود ذلك إلى توفير‬ ‫هذا النوع لكامل فضاء األسماء وليس لجزء معين من المشروع ويمكن للمترجم الوصول إلى تعريف‬ ‫النوع متى احتاج لذلك من خالل فضاء األسماء‪.ToString(myDirection‬‬ ‫.WriteLine("string equivalent={0}".byte‬‬ ‫.

WriteLine("enter name direction:‬‬ ‫.myString‬‬ ‫.ToSring‬‬ ‫.‬‬ ‫‪west = 4‬‬ ‫}‬ ‫‪class Program‬‬ ‫{‬ ‫)‪static void Main(string[] args‬‬ ‫{‬ ‫.ToSring‬‬ ‫.)‪Console.Parse(typeof(enumerationType).))(‪myString = Convert.‫وبالطبع فإنه في هذه الحالة عل ينا االنتباه إلى أن ليست جميع قيم ‪ byte‬لها قيم مقابلة في النوع‬ ‫‪ orientation‬يستطيع تخزين قيم ‪ byte‬أخرى غير تلك األربعة إال أن هذا قد يؤثر على منطق التطبيق‬ ‫الحقا‪.ReadLine‬‬ ‫‪orientation myDirection1 =(orientation )Enum .string‬‬ ‫وكبديل لذلك يمكننا استخدام األمر )(‪ ToString‬على المتحول نفسه فالشيفرة التالية تعطي نفس النتيجة‬ ‫التي سنحصل عليها باستخدام )(‪:Convert.ReadLine‬‬ ‫}‬ ‫}‬ ‫}‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪113 -‬‬ ‫‪-‬‬ .)‪directionString = Convert.enumeratioVal‬‬ ‫.ToString(Console.)‪ueString‬‬ ‫هنا تم استخدام عامل جديد وهو ‪ typeof‬والذي يعيد لنا نوع بيانات الحد يمكننا استخدام هذه الصيغة مع‬ ‫النوع ‪ orientation‬كما يلي‪:‬‬ ‫‪namespace Console_Enumeration‬‬ ‫{‬ ‫‪enum orientation : byte‬‬ ‫{‬ ‫‪north = 1.‬‬ ‫ولكي نتمكن من الحصول على القيمة النصية من قيمة تعداد سنستخدم األمر )(‪:Convert.‬‬ ‫‪south = 2.)"‪Console.ToString(myDirection‬‬ ‫إن استخدام التشكيل ‪ string‬ال يعمل هنا باعتبار أن المعالجة المطلوبة هنا أكثر تعقيدا من مجرد وضع‬ ‫البيانات المخزنة في متحول تعداد من نوع ‪.WriteLine(myDirection1‬‬ ‫.)(‪Console.)‪Parse (typeof (orientation).‬‬ ‫‪east = 3. ToString‬‬ ‫إن تحويل قيمة نصية إلى قيمة من نوع مجموعة قيم هو أمر ممكن فيما عدا أن الصيغة الالزمة لتحقيق‬ ‫ذلك معقدة نوعا ما فهناك أمر خاص لهذا النوع من التحويل وهو )(‪ Enum.‪string myString‬‬ ‫.)(‪directionString = myDirection.‬‬ ‫.Parse‬ويمكننا استخدامه‬ ‫كما يلي‪:‬‬ ‫‪(enumerationType)Enum.

WriteLine(myDay‬‬ ‫}‬ ‫}‬ ‫}‬ ‫‪ -3‬نفذ التطبيق بالضغط على مفتاح ‪ Ctrl+F5‬ومن ثم قم بإدخال رقم يقع بين ‪ 9‬و ‪ 6‬و ليكن ‪3‬‬ ‫فيظهر الشكل (‪.C#‬‬ ‫تطبيق أخر حول التعدادات‪:‬‬ ‫‪ -1‬قم بإنشاء تطبيق ‪ Console‬جديد باسم ‪.)5-19‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪114 -‬‬ ‫‪-‬‬ .9‬‬ ‫وبالطبع فإنه ليست جميع السالسل النصية تستطيع أن تشكل قيما لـ ‪ orientation‬فإذا كانت قيمة المتحول‬ ‫النصي ‪ myString‬هي "‪ " left‬مثال فإنه ليست هناك أية قيمة موافقة ضمن التعداد ‪ orientation‬وفي‬ ‫حالة كهذه سنحصل على خطأ من المترجم وكما في كل شيء ضمن ‪ C#‬فإن هذه القيم متحسسة لحالة‬ ‫الحرف أيضا وبالتالي إذا كانت قيمة المتحول ‪ myString‬هي "‪ "North‬فإننا سنحصل على خطأ أيضا‬ ‫الن ‪ North‬ليست ‪ north‬في ‪.Mon‬‬ ‫.)‪Console.WriteLine("Friday: {0}".‬‬ ‫‪Fri.Fri‬‬ ‫.‪int WeekdayStart = (int)Days.‬‬ ‫‪Wed.))(‪number = Convert.)"‪Console.)‪Console. WeekdayStart‬‬ ‫. WeekdayEnd‬‬ ‫.‬‬ ‫‪tue.WriteLine("Monday: {0}".‪int WeekdayEnd = (int)Days.ReadLine‬‬ ‫.Console enum days‬‬ ‫‪ -2‬أضف الشيفرة البرمجية التالية إلى محرر نصوص ‪.‬‬ ‫‪Sat‬‬ ‫}‬ ‫‪class Program‬‬ ‫{‬ ‫)‪static void Main(string[] args‬‬ ‫{‬ ‫. ‫الشكل(‪)5.)‪Console.C#‬‬ ‫‪namespace Console_enum_days‬‬ ‫{‬ ‫‪enum Days‬‬ ‫{‬ ‫‪Sun.‪Days myDay = (Days)number‬‬ ‫.‪int number‬‬ ‫.ToInt32(Console.‬‬ ‫‪Mon.WriteLine("enter a number btween 0 to 6:‬‬ ‫.‬‬ ‫‪thu.

WriteLine("Friday: {0}". WeekdayStart‬‬ ‫.)"‪Console.))(‪number = Convert.WriteLine("Monday: {0}".)‪Console.‪Days myDay = (Days)number‬‬ ‫ومن ثم قمنا بإظهار قيمة المتحول ‪ myDay‬على شاشة ‪ Console‬باستخدام الشيفرة‪:‬‬ ‫.)‪Console.WriteLine("enter a number btween 0 to 6:‬‬ ‫ليقوم بعد ذلك البرنامج بإسناد قيمة الدخل إلى المتحول ‪ number‬بعد تحويل قيمة الدخل إلى النوع ‪int32‬‬ ‫باستخدام الشيفرة‪:‬‬ ‫.ReadLine‬‬ ‫ومن ثم قمنا بالتصريح عن متحول جديد باسم ‪ myDay‬من النوع ‪ Days‬وأسندنا له قيمة المتحول‬ ‫‪ number‬بعد تحويله للنوع ‪ Days‬قسرا باستخدام الشيفرة‪:‬‬ ‫.)‪Console. ‫الشكل (‪)5.ToInt32(Console.19‬‬ ‫كيفية العمل‪:‬‬ ‫‪How it Works:‬‬ ‫في الشيفرة السابقة قمنا بالتصريح عن تعداد باسم ‪ Days‬يحوي أيام االسبوع ضمن فضاء االسماء‬ ‫‪ namespace‬ومن ثم قمنا بالتصريح عن ثالث متحوالت (‪،WeekdayStart،number‬‬ ‫‪ )WeekdayEnd‬من النوع ‪ int‬حيث اسند للمتحول ‪ WeekdayStart‬رقم يوم االثنين ضمن التعداد‬ ‫وللمتحول ‪ WeekdayEnd‬رقم يوم الجمعة ضمن التعداد ومن ثم قمنا بإظهار قيم االسناد على شاشة‬ ‫‪ Console‬باستخدام الشيفرات‪:‬‬ ‫.WriteLine(myDay‬‬ ‫الصنف الثاني من أنواع المتحوالت في هذا الفصل هو البنية ‪( struct‬اختصارا لكلمة ‪ )structure‬تمثل‬ ‫البنية أجزاء مختلفة من البيانات يمكن ان يكون لكل جزء نوع مختلف فهي تمكننا من تعريف أنواعنا‬ ‫الخاصة من المتحوالت باالعتماد على هذه البنية على سبيل المثال لنفرض اننا نود حفظ مسار لموقع ما‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪115 -‬‬ ‫‪-‬‬ . WeekdayEnd‬‬ ‫ومن ثم طلبنا من المستخدم إدخال رقم يقع بين ‪ 9‬و‪ 6‬باستخدام الشيفرة‪:‬‬ ‫.

‪Orientation myDirection‬‬ ‫.>‪< accessibility > <type> <name‬‬ ‫إن >‪ <name‬يمثل اسم العضو أي المتحول و >‪ <type‬يمثل نوع العضو و أما >‪<accessibility‬‬ ‫فهو يمثل مدى الوصول إلى هذا الموضوع من خارج البنية‪.‪Public double distance‬‬ ‫}‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪116 -‬‬ ‫‪-‬‬ .‫بدءا من نقطة محددة حيث أن هذا المسار مؤلف من اتجاه ومسافة محسوبة باألميال ولتبسيط األمور فإننا‬ ‫سنفترض أن االتجاه هو واحد من االتجاهات األربعة المعروفة ضمن التعداد ‪ orientation‬في القسم‬ ‫السابق و أن المسافة باألميال ممثلة بالنوع ‪.‪Double myDistance‬‬ ‫ليس هناك أي خطا فيما قمنا به هنا إال أنه سيكون من األبسط لو استخدمنا متحول وحيد لحفظ هذه‬ ‫المعلومات‪.‬‬ ‫لنأخذ مثاال حيا للبنية‪:‬‬ ‫‪Struct route‬‬ ‫{‬ ‫.double‬‬ ‫واألن يمكننا استخدام متحولين منفصلين لتمثيل هذا المسار كما في الشيفرة التالية‪:‬‬ ‫.‪Public orientation direction‬‬ ‫.‬‬ ‫تعرف البنى باستخدام الكلمة ‪ struct‬كما يلي‪:‬‬ ‫> ‪Struct < typeName‬‬ ‫{‬ ‫> ‪< memberDeclarations‬‬ ‫}‬ ‫يتضمن القسم > ‪ < memberDeclarations‬تصريحات المتحوال ت (تسمى هذه المتحوالت بأعضاء‬ ‫البيانات ( ‪ ) date members‬لهذه البنية) بنفس األسلوب المعتاد تقريبا فكل تصريح لعضو سيأخذ الصيغة‬ ‫التالية‪:‬‬ ‫.

double myDistance.C# ‫ أضف الشيفرة البرمجية التالية إلى محرر نصوص‬-2 namespace Console_Struct_direction { enum orientation : byte { north = 1. Console . } while ((myDirection <1)||(myDirection >4)). ‫ املهندس حسام الدين الرز‬:‫إعداد‬ 117 - - .5. south = 2. int myDirection.direction = orientation. myRoute. myDirection =Convert .ToInt32 (Console .‫ للمتحوالت في الفصل التالي فال تكترث بها األن‬scope ‫سنتحدث عن مدى الوصول‬ ‫ بحد ذاته ال يأخذ قيمة حرفية مباشرة وإنما إسناد القيم الحرفية يتم على مستوى أعضاءه‬myRoute ‫أن‬ :‫ بالشكل‬myRoute ‫أي يمكننا استخدام المتحول‬ myRoute.ReadLine ()).Console Struct direction ‫ جديد باسم‬Console ‫ قم بإنشاء تطبيق‬-1 . myDistance =Convert .ToDouble (Console .‫ يمثل األن نوعا جديدا من أنواع المتحوالت وأما‬route ‫ وبالتالي فإن‬route ‫لقد عرفنا هنا بنية باسم‬ ‫ وبالتالي يمكننا أن نستخدم هذه البنية‬route ‫ فهي أعضاء تنتمي إلى البنية‬distance‫ و‬direction :‫ كالمعتاد‬route ‫بالتصريح عن متحول من نوع‬ Route myRoute. east = 3. public double distance.ReadLine ()).WriteLine ("Input a distance").distance = 2. } class Program { static void Main(string[] args) { route myRoute. west = 4 } struct route { public orientation direction.north.WriteLine ("Select a direction:"). Console.WriteLine("1) Nourth\n2)South\n3)East\n4)West"). :‫مالحظة‬ . do { Console . :‫تطبيق حول استخدام البنى‬ .

while‬‬ ‫وبالتالي فإن هذه الحلقة ستمنع أي قيمة سيدخلها المستخدم ليست ‪ 1‬أو ‪ 2‬أو ‪ 3‬أو ‪ 4‬حصرا وفي حال أدخل‬ ‫المستخدم قيمة مخالفة فسيعاد التطبيق سؤال المستخدم عن اإلدخال من جديد وسبب تحديد هذه القيم هو‬ ‫أنها القيم الوحيدة التي تمثل االتجاهات المعرفة ضمن التعداد ‪.direction =(orientation )myDirection‬‬ ‫. ‪myRoute .11‬‬ ‫كيفية العمل‪:‬‬ ‫‪How it Works:‬‬ ‫يتم التصريح عن البنى كالتعدادات خارج الجسم الرئيسي للشيفرة التنفيذية لقد قمنا بالتصريح عن البنية‬ ‫‪ route‬ضمن فضاء أسماء المشروع مع مجموعة القيم ‪:orientation‬‬ ‫‪enum orientation : byte‬‬ ‫{‬ ‫‪north = 1.‬‬ ‫‪west = 4‬‬ ‫}‬ ‫‪struct route‬‬ ‫{‬ ‫.distance =myDistance‬‬ ‫‪Console . ‫.distance‬‬ ‫}‬ ‫}‬ ‫}‬ ‫‪ -3‬نفذ التطبيق بالضغط على مفتاح ‪ Ctrl+F5‬ومن ثم قم بإدخال رقم الجهة ومن ثم قم بإدخال‬ ‫المسافة فيظهر الشكل (‪.myRoute .myRoute .)5-11‬‬ ‫الشكل (‪)5.direction . ‪myRoute .‬‬ ‫‪east = 3.‪public double distance‬‬ ‫}‬ ‫إن الجسم الرئيسي للشيفرة التالية له بنية مشابهة لبعض األمثلة و التطبيقات التي رأيناها مسبقا حيث أن‬ ‫الشيفرة التالية طلبت من المستخدم إدخاال ما ثم قامت بعرض هذا اإلدخال لقد قمنا هنا بعملية تحقق من‬ ‫المستخدم بسيطة و ذلك بوضع قيمة االتجاه التي سيدخلها المستخدم ضمن حلقة من نوع ‪do….‬‬ ‫‪south = 2.‪public orientation direction‬‬ ‫.) ‪"a distance of {1}".WriteLine ("myRoute specifies a direction of {0} and "+‬‬ ‫.orientation‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪118 -‬‬ ‫‪-‬‬ .

memberVar ‫إن أي وصول إلى أعضاء البنية يتم بالصورة ذاتها والتعابير التي لها الشكل‬ .ToDouble (Console . myRoute . myRoute . ‫ املهندس حسام الدين الرز‬:‫إعداد‬ 119 - - .ToInt16(Console. ‫ في‬myRoute. Person. anotherDistance = myRoute.‫بنفسك ال تقلق فلقد أصبحت قادرا على قراءة شيفرات كهذه بشكل جيد‬ .WriteLine("input your Name").WriteLine("input your Age").4 :‫تطبيق أخر حول البنى‬ ‫) وعمره‬adresse( ‫) وعنوانه‬name( ‫سوف نقوم في هذا التطبيق ببناء بنية تسمح بتخزين اسم المستخدم‬ ‫ وسأترك لك التعليق وقراءة هذه الشيفرة‬Console ‫) ومن ثم تقوم بإظهار هذه البيانات على شاشة‬age( .ReadLine(). Console. structVar.WriteLine("input your Adresse").memberVar ‫تمثل متحوال من نفس نوع‬ :‫وبالتالي ووفقا للشيفرة السابقة يمكننا كتابة‬ Double anotherDistance.ReadLine ()).distance ‫ حاصل ضرب قيمة العضو‬anotherDistance ‫حيث سيتضمن المتحول‬ .2.‫ في المتحول‬route ‫إن النقطة المثيرة في هذه الشيفرة متمركزة بالطريقة التي تشير فبها إلى أعضاء البنية‬ . public string adresse.Console Struct Persons ‫ جديد باسم‬Console ‫ قم بإنشاء تطبيق‬-1 .C# ‫ أضف الشيفرة البرمجية التالية إلى محرر نصوص‬-2 namespace Console_Struct_Persons { struct persons { public string name.myRoute myRoute .4. Console.name = Console. Person. Console.direction =(orientation )myDirection .distance =myDistance .age = Convert.distance ‫و يمكن نا ببساطة الحصول على قيمة دخل المستخدم ووضعها ضمن العضو‬ :‫باستخدام السطر‬ myRoute . } class Program { static void Main(string[] args) { persons Person.distance*2.distance = Convert .adresse = Console.ReadLine()).ReadLine(). public short age. Person.

Person.)5-12‬‬ ‫الشكل (‪)5-12‬‬ ‫هناك شيء مشترك لجميع األنواع التي تعرفنا عليها حتى األن أال وهو أن جميعها ال يستطيع تخزين‬ ‫سوى قيمة واحدة فقط (أو مجموعة واحدة من القيم وذلك بالنسبة للبنى) نحتاج في بعض األحيان إلى‬ ‫حفظ الكثير من البيانات التي تنتمي إلى نفس النوع وبحيث تكون مرتبطة مع بعضها البعض بصورة أو‬ ‫بأخرى‪."‪String friendName3 = "Omar Ahmad‬‬ ‫ولكن أال تؤيدني بإن استخدام هذه الطريقة غير عملي أبدا؟‬ ‫فإذا فرضنا أن لدينا عشرة أسماء نود حفظها بنفس الصورة عندئذ فإننا بحاجة على عشر متحوالت!‬ ‫واألسوأ من ذلك إذا كان لدينا مائة اسم وأردنا أن نعدل فيها (كأن نضع عبارة ‪ Mr.adresse.age‬‬ ‫}‬ ‫}‬ ‫}‬ ‫‪ -3‬نفذ التطبيق بالضغط على مفتاح ‪ Ctrl+F5‬ومن ثم قم بإدخال االسم والعنوان والعمر فيظهر‬ ‫الشكل (‪.‬‬ ‫الحل البديل لهذا الصداع يقتضي باستخدام المصفوفة ‪ array‬فالمصفوفات عبارة عن قوائم مفهرسة من‬ ‫المتحوالت موضوعة ضمن متحول وحيد على سبيل المثال لنفترض أن لدينا مصفوفة تحتفظ باألسماء‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪120 -‬‬ ‫‪-‬‬ . your Adresse is: {1} " +‬‬ ‫‪" . Person."‪String friendName1 = "Mohamed ALmesri‬‬ ‫.)‪Person. your age is: {2}".‬‬ ‫.‬‬ ‫على سبيل المثال لنفترض أننا نود حفظ أسماء أصدقائنا ضمن متحوالت الستخدام هذه األسماء لغرض‬ ‫ما عندئذ سنستخدم متحوالت كما يلي‪:‬‬ ‫."‪String friendName2 = "Nader ALali‬‬ ‫. ‫‪Console.WriteLine("your Name is:{0} .name.‬في بداية كل اسم)‬ ‫عندئذ فإننا بحاجة إلى كتابة سطر برمجي للقيام بذلك حيث أن الحلقات ال تخدمنا كثيرا هنا‪.

i".i++‬‬ ‫{‬ ‫.‬‬ ‫يمكن لـ >‪ <baseType‬أن تمثل أي نوع كان سواء كان نوع بسيطا أو تعداد أو بنية أما >‪<name‬‬ ‫فتمثل اسم المصفوفة (أو اسم متحول المصفوفة)‪.string‬‬ ‫يمكننا التصريح عن المصفوفة وفقا للصيغة التالية‪:‬‬ ‫.>‪<baseType> [] <name‬‬ ‫إن هذا مشابه جدا للتصريح ع ن المتحوالت العادية والفارق هنا فقط في وجود القوسين "] [" بعد نوع‬ ‫المتحول‪. friendNames[i‬‬ ‫}‬ ‫للمصفوفات نوع أساسي (‪ )base type‬واحد أي أن جميع عناصر المصفوفة تنتمي على هذا النوع وفي‬ ‫حالة مصفوفة أسماء أصدقائنا ‪ friendNames‬السابقة فإنه من الواضح أن هذه المصفوفة من نوع‬ ‫‪.‪myIntArray[10] = 5‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪121 -‬‬ ‫‪-‬‬ .‪int[] myIntArray‬‬ ‫.‬‬ ‫ولكي نتمكن من استخدام المصفوفة فإن علينا أن نهيئها فال يمكننا الوصول إلى عناصر المصفوفة أو‬ ‫إسناد القيم إليها بالشكل‪:‬‬ ‫.) ]‪Console. i<3 .‬‬ ‫إن دليل العنصر عبارة عن عدد صحيح حيث يبدأ الترقيم في المصفوفة من الرقم ‪ 9‬وهذا يعني أن‬ ‫العنصر األول من المصفوفة له الدليل ‪ 9‬والعنصر الثاني من المصفوفة له الدليل ‪ 1‬وهكذا وبالتالي إذا‬ ‫أردنا أن نطبع جميع عناصر المصفوفة ‪ friendNames‬فإننا سنستخدم حلقة ‪ for‬كما يلي‪:‬‬ ‫)‪for (int i=0 .‫الثالثة السابقة ولنسميها باالسم ‪ friendNames‬عندئذ يمكننا الوصول إلى عناصر المصفوفة بتحديد‬ ‫دليل العنصر أي موقعه من المصفوفة أو فهرسه (‪ )index‬وذلك وفقا للصيغة التالية‪:‬‬ ‫]>‪friendNames[<index‬‬ ‫حيث سنضع دليل العنصر ضمن األقواس "] ["‪.WriteLine("Name with index of {0}:{1}.

10. 9. 99‬‬ ‫فإن أزلنا الكلمة ‪ const‬من تصريح المتحول سيخفق المترجم في ترجمة الشيفرة‪.]‪Int [ ] myIntArray = new int [arraySize‬‬ ‫ويمكننا أن ندمج الطريقتين مع بعضهما البعض بالشكل‪:‬‬ ‫. 2.‪int[] myIntArray‬‬ ‫.‫هناك طريقتان لتهيئة المصفوفة إما أن نحدد المحتوى الكامل للمصفوفة مباشرة بهيئة العناصر الحرفية‬ ‫أو يمكننا تحديد حجم المصفوفة ومن ثم استخدام الكلمة ‪ new‬لتهيئة جميع عناصر المصفوفة‪.int‬‬ ‫والطريقة االخرى تتطلب صيغة كالشكل‪:‬‬ ‫.‬‬ ‫وكما في أنواع المتحوالت األخرى فإننا لسنا بحاجة لتهيئة المصفوفة في نفس السطر الذي نصرح عنها‬ ‫فيه أي أن الشيفرة التالية صحيحة‪:‬‬ ‫.‬‬ ‫وبالتالي فلكي نهيئ المصفوفة ‪ myIntArray‬فإننا سنكتب‪:‬‬ ‫.}‪int [ ] myIntArray = new int [arraySize] {5.‪const int arraySize=5‬‬ ‫. 9. 10.} ‪int[] myIntArray = { 5.} ‪int[] myIntArray = new int[10] { 5. 2. 10. 2. 99‬‬ ‫وفي حالة كهذه يجب أن يتطابق حجم المصفوفة مع القيم الحرفية المسندة إليها فال يمكننا على سبيل‬ ‫المثال كتابة ما يلي‪:‬‬ ‫.} ‪int[] myIntArray = new int[5] { 5. 9.]>‪<arrayType> [ ] arrayName=new <arrayType> [<size‬‬ ‫حيث >‪ <size‬تمثل عدد عناصر المصفوفة ناقصا واحد (بسبب بدء ترقيم العناصر من الصفر)‪.]‪myIntArray = new int[5‬‬ ‫والشكل (‪ )5-13‬يبين شكل المصفوفة أحادي ة البعد التي تحدثنا عنها فهي تتكون من سطر واحد وعدة‬ ‫اعمدة تمثل بعد أو حجم هذه المصفوفة‪. 2.‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪122 -‬‬ ‫‪-‬‬ . 10. 99‬‬ ‫هنا لقد عرفنا المصفوفة بأنها تستوعب ‪ 19‬عناصر بينما قمنا بتعريف خمسة عناصر فقط لذا فإن هذا‬ ‫سيتسبب في حدوث خطأ هناك مالحظة واحدة في استخدام هذا االسلوب للتصريح عن مصفوفة وهو أن‬ ‫حجم المصفوفة يجب أن يمثل قيمة حرفية أو متحوال ثابتا فقط على سبيل المثال‪:‬‬ ‫. 99‬‬ ‫للمصفوفة ‪ myIntArray‬هنا خمس عناصر وهي من نوع ‪.‬‬ ‫إن تحديد محتوى المصفوفة باستخدام القيم الحرفية يتطلب استخدام رمز الفاصلة "‪ "،‬لفصل العناصر‬ ‫عن بعضها البعض بحيث تتوضع هذه القيم ضمن القوسين "}{" كما يلي‪:‬‬ ‫. 9.

Length). .)5-14( ‫ فيظهر الشكل‬Ctrl+F5 ‫ نفذ التطبيق بالضغط على مفتاح‬-3 )5-14( ‫الشكل‬ :‫كيفية العمل‬ How it Works: ‫ وتهيئتها بثالث قيم ومن ثم سرد هذه‬friendNames ‫تقوم هذه الشيفرة بالتصريح عن مصفوفة باسم‬ ‫ لكي‬friendNames.Console Array Friend Name ‫ جديد باسم‬Console ‫ قم بإنشاء تطبيق‬-1 .Length. Console. i++) { Console.WriteLine("hare are {0} of my Friend". )5-13( ‫الشكل‬ :‫تطبيق حول استخدام المصفوفات‬ .WriteLine(friendNames[i]).C# ‫ أضف الشيفرة البرمجية التالية إلى محرر نصوص‬-2 namespace Console_Array_Friend_Name { class Program { static void Main(string[] args) { string[] friendNames = {"Mohamed ALmesri". for (int i = 0.WriteLine("hare are {0} of my Friend". i < friendNames. friendNames. friendNames. "Nader ALal".‫إن تلك الطريقة مفيدة للحصول على حجم المصفوفة‬ ‫ املهندس حسام الدين الرز‬:‫إعداد‬ 123 - - .Length).Length ‫ الحظ أننا استخدمنا التعبير‬for ‫القيم على شاشة الخرج بواسطة حلقة‬ :‫يعطينا عدد العناصر ضمن المصفوفة‬ Console. "Omar Ahmad"}. } } } } .

‫أما طباعة قيم المصفوفة بواسطة حلقة ‪ for‬فهو أمر سهل للغاية لكن احتمال الوقوع في خطأ في تعليمة‬ ‫‪ for‬كبير إذا غيرنا < إلى =< كما يلي‪:‬‬ ‫)‪for (int i = 0.foreach‬‬ ‫تسمح لنا حلقة ‪ foreach‬الوصول إلى جميع العناصر ضمن مصفوفة بصورة خطية ودون االهتمام‬ ‫بعدد العناصر ضمنها ولهذه الحلقة الصيغة التالية‪:‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪124 -‬‬ ‫‪-‬‬ . i++‬‬ ‫{‬ ‫. i <= friendNames.Length.WriteLine(friendNames[i‬‬ ‫}‬ ‫حيث سيؤدي ذلك إلى ظهور رسالة خطأكما في الشكل (‪:)5-15‬‬ ‫الشكل (‪)5-15‬‬ ‫فبالعودة إلى هذه الحلقة نالحظ أن الدورة األخيرة لهذه الحلقة هي الدورة التي تكون فيها قيمة ‪ i‬مساوية‬ ‫لـ ‪ 3‬وهذا يعني أن ما سيطبع في هذه الدورة هو العنصر ]‪ friendNames[3‬وهو في الحقيقة العنصر‬ ‫الرابع من المصفوفة وهو غير موجود وذلك يعتبر محاولة للوصول إلى عناصر خارج حدود المصفوفة‬ ‫وسيؤدي ذلك إلى حدوث خطأ‪.‬‬ ‫هناك نوع خاص من الحلقات تفيدنا في حالة كهذه أال وهي حلقات ‪.)]‪Console.

)‪Console.)‪Console.WriteLine(friendName‬‬ ‫}‬ ‫}‬ ‫}‬ ‫}‬ ‫إن خرج هذه الشيفرة هو تماما كخرج الشيفرة في التطبيق السابق‪.‬‬ ‫.Length‬‬ ‫) ‪foreach (string friendName in friendNames‬‬ ‫{‬ ‫. "Omar Ahmad‬‬ ‫.C#‬‬ ‫)‪static void Main(string[] args‬‬ ‫{‬ ‫.Console Array New Set‬‬ ‫‪ -2‬أضف الشيفرة البرمجية التالية إلى محرر نصوص ‪.}"‪"Nader ALal".WriteLine("hare are {0} of my Friend"."‪friendName="Gader Amen‬‬ ‫}‬ ‫إن هذه الشيفرة ستسبب في حدوث خطأ من المترجم أما باستخدام حلقة ‪ for‬العادية فإنه يمكننا تعديل‬ ‫محتوى المصفوفة كما نريد‪.‬‬ ‫تطبيق أخر حول استخدام المصفوفات‪:‬‬ ‫‪ -1‬قم بإنشاء تطبيق ‪ Console‬جديد باسم ‪. friendNames.]‪int[] Array = new int[5‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪125 -‬‬ ‫‪-‬‬ .‬‬ ‫إن الفرق الرئيسي بين استخدام هذه الطريقة واستخدام حلقة ‪ for‬العادية هو أن حلقة ‪ foreach‬تؤمن لنا‬ ‫وصوال محميا (للقراءة فقط) لمحتويات المصفوفة أي ال يمكننا تعديل محتويات المصفوفة ضمن الحلقة‬ ‫فال يمكننا على سبيل المثال كتابة شيفرة كهذه‪:‬‬ ‫) ‪foreach (string friendName in friendNames‬‬ ‫{‬ ‫. ‫)>‪foreach (<baseType> <name> in <array‬‬ ‫{‬ ‫‪// can use <name> for each element‬‬ ‫}‬ ‫س تقوم هذه الحلقة بالمرور عبر كل عنصر من عناصر المصفوفة وعند كل دورة من دورات هذه الحلقة‬ ‫سيمثل >‪ <name‬الواجهة التي سنتعامل من خاللها مع العنصر وبهذه الطريقة ال يمكننا أن نقع في خطأ‬ ‫محاولة الوصول إلى عناصر خارج المصفوفة وبالتالي يمكننا تعديل الشيفرة السابقة لتأخذ الشكل التالي‪:‬‬ ‫‪namespace Console_Array_Friend_Name‬‬ ‫{‬ ‫‪class Program‬‬ ‫{‬ ‫)‪static void Main(string[] args‬‬ ‫{‬ ‫‪string[] friendNames = { "Mohamed ALmesri".

i < Array. j.Length.ReadLine()).WriteLine("show element the array in the new set : " + element). j++) { if (Array[i] > Array[j]) { Temp = Array[i]. } } } foreach (int element in Array ) { Console. Array[j] = Temp. int i. i < Array.Length. i++) { Console. } for (i = 0. j < Array.Length. Array[i] = int.WriteLine("input a mount the element " + i). } } . Temp. Array[i] = Array[j]. for (i = 0.)5-16( ‫ فيظهر الشكل‬Ctrl+F5 ‫ نفذ التطبيق بالضغط على مفتاح‬-3 )5-16( ‫الشكل‬ :‫كيفية العمل‬ How it Works: int ‫في هذا التطبيق قمنا بالتصريح عن مصفوفة أحادية البعد خطية تحوي خمس عناصر من النوع‬ :‫باستخدام التعليمة‬ ‫ املهندس حسام الدين الرز‬:‫إعداد‬ 126 - - .Parse(Console. i++) { for (j = i + 1.

‬الالذقية إن تخزين معلومات كهذه يتطلب جدوال عناوين أعمدته و عناوين صفوفه تمثل اسماء‬ ‫المدن و أما ما داخل الجدول فهو يمثل المسافة بالكيلومترات بين كل مدينتين إن جدوال كهذا سيأخذ‬ ‫الشكل التالي‪:‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪127 -‬‬ ‫‪-‬‬ .)‪Console.]‪int[] Array = new int[5‬‬ ‫ومن ثم قمنا بالتصريح عن ثالث متحوالت من النوع ‪. i++‬‬ ‫{‬ ‫)‪for (j = i + 1.‪Array[j] = Temp‬‬ ‫}‬ ‫}‬ ‫}‬ ‫ومن ثم عملنا أخيرا على طباعة عناصر المصفوفة بالترتيب الجديد وذلك باستخدام تعليمة ‪.Length.]‪Array[i] = Array[j‬‬ ‫.‬حمص‪ .int‬‬ ‫ومن ثم قمنا ببناء حلقة إدخال تطلب من المستخدم إدخال قيمة كل عنصر من عناصر المصفوفة الخمس‬ ‫حيث تم هنا اسناد القيمة المدخلة إلى كل العنصر المقابل لها وذلك بعد تحويل االدخال على النوع ‪int32‬‬ ‫وذلك باستخدام طريقة جديدة للتحويل باستخدام العامل ‪ Parse‬وذلك باستخدام الشيفرة التالية‪:‬‬ ‫)‪for (i = 0.foreach‬‬ ‫قد تظن من العنوان الذي يشير له هذا القسم أننا نتحدث عن إضافة عملية رياضية إلى لغة ‪ C#‬فباإلضافة‬ ‫إلى المصفوفات الخطية )‪ (linear arrays‬التي تناولناها في السابق فإن لغة ‪ C#‬تدعم المصفوفات ثنائية‬ ‫وثالثية البعد والمصفوفات ذات ‪ N‬بعد أيضا‪. ‫.WriteLine("input a mount the element" + i‬‬ ‫. i < Array.Length.‬حلب‬ ‫‪.ReadLine‬‬ ‫}‬ ‫ومن ثم قمنا بتعشيش حلقتين األولى تبدأ من قيمة العنصر األول للمصفوفة والثانية تبدأ من قيمة العنصر‬ ‫الثاني إلى أن تنتهيان بأخر عنصر من المصفوفة حيث أن العمليات ضمن الحلقات تعمل على ترتيب‬ ‫عناصر المصفوفة ترتيبا تصاعديا من االصغر إلى األكبر وذلك باستخدام الشيفرة التالية‪:‬‬ ‫)‪for (i = 0.]‪Temp = Array[i‬‬ ‫. j < Array.))(‪Array[i] = int.Length. i++‬‬ ‫{‬ ‫.‬‬ ‫لنفترض على سبيل المثال أننا نود تخ زين المسافات بين المدن السورية األربعة التالية‪ :‬دمشق ‪.Parse(Console. j++‬‬ ‫{‬ ‫)]‪if (Array[i] > Array[j‬‬ ‫{‬ ‫. i < Array.

.{400. . j‬‬ ‫حيث تمثل ‪ i‬عدد االسطر و‪ j‬هو عدد االعمدة يمكننا أن نضع القيم مباشرة ضمن المصفوفة مع أخذ‬ ‫الفواصل بعين االعتبار عند تحديد موقع العنصر سنستخدم هنا أقواس "}{ " لتحديد القيم الحرفية لتلك‬ ‫المصفوفة لكل سطر‪:‬‬ ‫‪Double[.300. ‫حمص‬ ‫الالذقية‬ ‫حلب‬ ‫دمشق‬ ‫‪159‬‬ ‫‪399‬‬ ‫‪499‬‬ ‫‪9‬‬ ‫دمشق‬ ‫‪299‬‬ ‫‪359‬‬ ‫‪9‬‬ ‫‪499‬‬ ‫حلب‬ ‫‪259‬‬ ‫‪9‬‬ ‫‪359‬‬ ‫‪399‬‬ ‫الالذقية‬ ‫‪9‬‬ ‫‪259‬‬ ‫‪299‬‬ ‫‪159‬‬ ‫حمص‬ ‫مالحظة‪:‬‬ ‫البيانات الموجودة في هذا الجدول غير دقيقة وال تطابق الواقع‪.150}.359‬‬ ‫والشكل (‪ )5-17‬يبين كيفية تمثيل جدول المسافات السابق ضمن مصفوفة ‪:distances‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪128 -‬‬ ‫‪-‬‬ .‬‬ ‫ولكي نستطيع تمثيل جدول كهذا فإن علينا أن نستخدم مصفوفة ثنائية البعد إن تصريحا لمصفوفة ثنائية‬ ‫البعد يأخذ الصيغة التالية‪:‬‬ ‫.] distances = new double[i.200.‬‬ ‫.‬‬ ‫إن إسناد القيم لهذه المصف وفة يأخذ الصيغة نفسها أيضا وللتصريح عن مصفوفة ثنائية البعد وتهيئتها وفقا‬ ‫لجدول المسافات بين المدن ولتكن باسم ‪ distances‬فإننا سنكتب ما يلي‪:‬‬ ‫.]‪x=distances [2.350.400.1‬‬ ‫سيأخذ المتحول ‪ x‬هنا القيمة ‪ 350‬وذلك ألننا حددنا العنصر الثالث رقم (‪ )2‬من البعد األول والثاني رقم‬ ‫(‪ )1‬من البعد الثاني وهذا يوافق العنصر ذو القيمة ‪.>‪<baseType> [ .0.350.‪double x‬‬ ‫.0‬‬ ‫ولكي نتمكن من الوصول إ لى العناصر كال على حدة ضمن مصفوفة كهذه فإننا سنستخدم تعبيرا كهذا‪:‬‬ ‫.0.}}‪{300.250. ] <name‬‬ ‫وبالنسبة لمصفوفات ذات أبعاد أكبر فإننا سنضع فواصل إضافية حيث تمثل كل فاصلة بعدا جديدا على‬ ‫سبيل المثال‪:‬‬ ‫.]‪Double[.] distances ={{0.200}.>‪<baseType> [ . ] <name‬‬ ‫يمثل ذلك تصريحا لمصفوفة رباعية البعد‪.{150.250}.

350..)‪Console.0‬‬ ‫]‪distances[1.250}.] distances ={{0.1‬‬ ‫]‪distances[1.150}.{150.400.3‬‬ ‫]‪distances[1..WriteLine(distance‬‬ ‫}‬ ‫.250.2‬‬ ‫‪..‬‬ ‫. ‫الشكل (‪)5-17‬‬ ‫تمكننا حلقة ‪ foreach‬من الوصول إلى جميع العناصر بطريقة متعددة األبعاد كما في المصفوفة الخطية‬ ‫أحادية البعد على سبيل المثال‪:‬‬ ‫‪Double[.ReadLine‬‬ ‫ووفقا لذلك فإن طباعة العناصر سيأخذ الشكل التالي‪:‬‬ ‫]‪distances[0.0.0.}}‪{300.1‬‬ ‫]‪distances[0.{400..200}.0‬‬ ‫)‪foreach (double distance in distances‬‬ ‫{‬ ‫.)(‪Console.200.‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪129 -‬‬ ‫‪-‬‬ .350.2‬‬ ‫]‪distances[0.0‬‬ ‫]‪distances[0...300.

:‫تطبيق حول استخدام المصفوفات متعددة األبعاد‬ .] Matrice = new int[3. j]). j <= 3. j <= 3.Parse(Console. i++) { for (j = 0. i++) { for (j = 0. i <= 2." + j + ")").ReadLine()).)5. j. for (i = 0.)5-18( ‫ فيظهر الشكل‬Ctrl+F5 ‫ نفذ التطبيق بالضغط على مفتاح‬-3 . j++) { Console. Matrice[i. i <= 2. } } . j++) { Console.C# ‫ أضف الشيفرة البرمجية التالية إلى محرر نصوص‬-2 static void Main(string[] args) { int[.Console Multi-dimensional Arrays ‫ جديد باسم‬Console ‫ قم بإنشاء تطبيق‬-1 .WriteLine("a mount element :(" + i + ".WriteLine("input a mount element :(" + i + ". 4]. } } for (i = 0. int i." + j + ") of array =" + Matrice[i.18( ‫الشكل‬ ‫ املهندس حسام الدين الرز‬:‫إعداد‬ 130 - - . j] = int.

3}.{1.‪int[][] jaggedIntArry‬‬ ‫لألسف فإن تهيئة مصفوفة كهذه ليس بسهولة تهيئة المصفوفات متعددة األبعاد فال يمكننا على سبيل المثال‬ ‫كتابة التالي‪:‬‬ ‫.2.2‬‬ ‫لدينا خياران لتهيئة مصفوفة المصفوفات يمكننا أن نهيئ المصفوفة التي تتضمن مصفوفات أخرى‬ ‫(سأسمي هذه المصفوفات بالمصفوفات الفرعية للتبسيط) ومن ثم تهيئة المصفوفات الفرعية وفقا لما يلي‪:‬‬ ‫.}}‪jaggedIntArray = {{1.{1}. ‫كيفية العمل‪:‬‬ ‫‪How it Works:‬‬ ‫في هذا التطبيق قمنا بالتصريح عن مصفوفة ثنائية البعد ومن ثم استخدمنا تعشيش الحلقات من أجل إدخال‬ ‫قيم عناصر هذه المصفوفة ومن ثم قمنا أيضا باستخدام تعشيش الحلقات لطباعة عناصر هذه المصفوفة‪.‬‬ ‫هناك طريقة في ‪ C#‬الستخدام مصفوفات غير متجانسة () وهي المصفوفات التي تكون لها صفوف‬ ‫بأحجام مختلفة وللقيام بذلك فإننا نحتاج لمصفوفة يمثل فيها كل عنصر مصفوفة بحد ذاتها أي أنه يمكننا‬ ‫أن نشكل مصفوفة عناصرها عبارة عن مصفوفات أيضا والشرط الوحيد لصحة ذلك هو أن تكون األنواع‬ ‫األساسية لهذه المصفوفات واحدة‪.]‪jaggedIntArray[0] = new int[3‬‬ ‫.‬‬ ‫إن صيغة التصريح عن مصفوفة مصفوفات يأخذ الصيغة التالية حيث أننا سنحدد مجموعة من األقواس‬ ‫"][" كما يلي‪:‬‬ ‫.‬‬ ‫إن المصفوفات متعددة األبعاد التي تناولناها في القسم السابق تأخذ شكال مستطيال يسمى هذا النوع من‬ ‫المصفوفات بالمصفوفات المستطيلة ( ‪ )rectangular arrays‬وذلك ألن كل صف له الحجم نفسه ولقد‬ ‫رأينا ذلك في مثال المسافات بين المدن‪.]‪jaggedIntArray[1] = new int[4‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪131 -‬‬ ‫‪-‬‬ .][]‪jaggedIntArray = new int[2‬‬ ‫.]‪jaggedIntArray =new int [3] [4‬‬ ‫وحتى إن استطعنا القيام بذلك فإن هذا لن يفيد باعتبار أن هذا يعني إنشاء مصفوفة لمصفوفات متجانسة‬ ‫وهو األمر الذي نستطيع تحقيقه باستخدام مصفوفات متعددة االبعاد بجهد أقل من ذلك وال يمكننا كتابة‬ ‫التالي‪:‬‬ ‫.

2.‬‬ ‫أو يمكننا استخدام نموذج معدل ألسلوب التهيئة السابق بحيث يتضمن إسناد القيم الحرفية إلى المصفوفات‬ ‫مباشرة‪:‬‬ ‫.2.8}.)‪Console.new int [] {1.WriteLine(divisor‬‬ ‫}‬ ‫}‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪132 -‬‬ ‫‪-‬‬ .‬‬ ‫‪new‬‬ ‫‪int [] {1.3.2.‬‬ ‫‪new‬‬ ‫‪int [] {1.10‬‬ ‫إن الشيفرة التالية ستخفق في العمل (وستعطي خطأ)‪:‬‬ ‫)‪foreach (int divisor in divisor1TO10‬‬ ‫{‬ ‫.2.‬‬ ‫‪new‬‬ ‫.)‪Console.6}.‬‬ ‫‪new‬‬ ‫‪int [] {1.3.‬‬ ‫‪new‬‬ ‫‪int [] {1.‬‬ ‫‪new‬‬ ‫‪int [] {1.‬‬ ‫‪new‬‬ ‫‪int [] {1.2}.new int [] {1}.‬‬ ‫‪new‬‬ ‫‪int [] {1.2.2‬‬ ‫يمكننا استخدام حلقات ‪ foreach‬مع المصفوفات غير المتجانسة إال أننا نحتاج إلى تعشيش حلقتين من‬ ‫حلقات ‪ foreach‬للحصول على عناصر المصفوفات الفرعية للمصفوفة لنفترض أن لدينا مصفوفة غير‬ ‫متجانسة تتضمن عشرة مصفوفات وكل مصفوفة فرعية من هذه المصفوفات هي مصفوفة أعداد صحيحة‬ ‫تمثل األعداد التي تقبل القسمة على موقع هذه المصفوفة الفرعية من المصفوفة الرئيسة (على سبيل المثال‬ ‫المصفوفة الخامسة) ذات الرقم ‪ 4‬تتضمن عنصرين فقط ‪ 1‬و‪ 5‬ألن العدد ‪ 5‬ال يقبل القسمة غال على هذين‬ ‫الرقمين فقط‪:‬‬ ‫‪int [][] divisors1To10 = {new int‬‬ ‫‪[] {1}.3}.3}.5}.9}.5.}}‪int [] {1.}}‪jaggedIntArray={new int[] {1.‫حيث تقرا هذه المصفوفة بأنها مصفوفة مصفوفات تحوي على مصفوفتين (الرقم ‪ )2‬المصفوفة رقم ‪9‬‬ ‫هي مصفوفة خطية احادية البعد تحوي على ثالثة عناصر والمصفوفة رقم ‪ 1‬هي مصفوفة خطية أحادية‬ ‫البعد تحوي على أربعة عناصر‪.4}.7}.WriteLine(divisor‬‬ ‫}‬ ‫إن ذلك يعود على أن المصفوفة ‪ divisors1To10‬تتضمن عناصر من النوع ][‪ int‬وليست عناصر من‬ ‫النوع ‪ int‬وبالتالي فإننا سنحتاج إلى حلقتي ‪ foreach‬الخارجية للمرور على المصفوفات والداخلية‬ ‫للمرور على عناصر كل مصفوفة كما يلي‪:‬‬ ‫)‪foreach (int divisorofInt in divisor1TO10‬‬ ‫{‬ ‫)‪foreach (int divisor in divisorofInt‬‬ ‫{‬ ‫.‬‬ ‫‪new‬‬ ‫‪int [] {1.4.

‬‬ ‫‪SyncRoot‬‬ ‫يعطي دليل العنصر األول في البعد المحدد من المصفوفة‬ ‫‪GetLowerBound‬‬ ‫يعطي دليل العنصر األخير في البعد المحدد من المصفوفة‬ ‫‪GetUpperBound‬‬ ‫يعطي دليل عنصر من المصفوفة طبعا دليل أول عنصر مشابه‬ ‫‪IndexOf‬‬ ‫يعطي قيمة عنصر من مصفوفة بتحديد دليله‬ ‫‪GetValue‬‬ ‫يعطي نوع بيانات المصفوفة‪.‬‬ ‫‪SetValue‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪133 -‬‬ ‫‪-‬‬ .)‪Console.‬‬ ‫يعطي قيمة منطقية ‪ True‬أو ‪ False‬تعبر فيما إذا كانت المصفوفة‬ ‫‪IsReadOnly‬‬ ‫للقراءة فقط‬ ‫يعطي قيمة تشير فيما إذا كان الوصول إلى المصفوفة تتم مزامنة‬ ‫‪IsSynchronized‬‬ ‫(موضوع آمن)‪.‬‬ ‫‪Sort‬‬ ‫تقوم بعكس ترتيب عناصر المصفوفة‬ ‫‪Reverse‬‬ ‫لتحويل المصفوفة إلى متغير نصي‬ ‫‪ToString‬‬ ‫تحدد عدد االبعاد في المصفوفة وتسمى رتبة المصفوفة‬ ‫‪Rank‬‬ ‫يعطي قيمة منطقية ‪ True‬أو ‪ False‬تعبر فيما إذا كان حجم المصفوفة‬ ‫‪IsFixedSize‬‬ ‫متغير أم ثابت‪.‬‬ ‫تحدد طول عناصر المصفوفة بعدد صحيح ‪ 64‬بت‬ ‫‪LongLength‬‬ ‫يعطي كائن يمكن استخدامه لمزامنة الوصول إلى المصفوفة‪.WriteLine(divisor‬‬ ‫وكما ترى فإن صيغة استخدام المصفوفات غير المتجانسة معقدة نوعا ما وفي معظم االحيان يكون من‬ ‫االفضل استخدام المصفوفات المستطيلة أو استخدام ابسط للتخزين على كل حال هناك أوضاع قد تجبر‬ ‫فيها على استخدام هذا النوع من المصفوفات‪.‬‬ ‫تحتوي المصفوفات على بعض الخصائص والدوال التي قد تساعدك في العمل عليها وأشهر هذه‬ ‫الخصائص والدوال وأكثرها استخداما مبين في الجدول التالي‪:‬‬ ‫االستخدام‬ ‫الخاصية أو الدالة‬ ‫تحدد طول المصفوفة عدد العناصر بعدد صحيح ‪ 32‬بت‬ ‫‪Length‬‬ ‫تقوم بترتيب عناصر المصفوفة تصاعديا وترتيب هجائي إذا كانت نصية‪. ‫توضيح‪:‬‬ ‫لقد نوهنا قبل ذلك أن بإمكاننا عدم وضع شيفرة جسم الحلقة أو جسم العبارة الشرطية ضمن كتلة برمجية‬ ‫أي وضع الشيفرة ضمن االقواس "}{" وذلك إذا كانت هذه الشيفرة تمثل سطرا برمجيا واحدا فقط وبالتالي‬ ‫فإن الشيفرة التالية مطابقة تماما للسابقة‪:‬‬ ‫)‪foreach (int divisorofInt in divisor1TO10‬‬ ‫)‪foreach (int divisor in divisorofInt‬‬ ‫.‬‬ ‫‪GetType‬‬ ‫يعمل على استبدال عنصر من المصفوفة بعنصر أخر يحدده المستخدم‪.

Console. arr1.WriteLine("Get UpperBound:\t{0}".WriteLine("Get Length:\t{0}".GetUpperBound(0)).Clear(arr1. i).WriteLine("Rank:\t{0}". Console. Array.GetLength(0)).WriteLine("Synchronized:\t{0}". Console. 26. SyncHronized. printArray(arr1). arr1. printArray(arr1).Copy(arr1. 6 }. arr1. Console. :‫تطبيق حول استخدام خصائص ودوال المصفوفات‬ .WriteLine("Get Type:\t{0}".Console Arrays properties ‫ جديد باسم‬Console ‫ قم بإنشاء تطبيق‬-1 . 5). Console. arr2. Array.GetType()). fixedSize). int[] arr2 = new int[5].WriteLine("Read Only:\t{0}".C# ‫ أضف الشيفرة البرمجية التالية إلى محرر نصوص‬-2 class Program { static void printArray(int[] arr) { Console.WriteLine("Get LongLength:\t{0}".GetLowerBound(0)). arr1. readOnly.Length.Rank. 0). fixedSize = arr1. Console. SyncHronized = arr1.GetLongLength(0)).)5-19( ‫ فيظهر الشكل‬Ctrl+F5 ‫ نفذ التطبيق بالضغط على مفتاح‬-3 ‫ املهندس حسام الدين الرز‬:‫إعداد‬ 134 - - . 14. Array.GetValue(4)).Reverse(arr1).WriteLine("Get LowerBound:\t{0}". len = arr1. foreach (int i in arr) { Console. Console. arr1. rank. Console. arr1. Console. SyncHronized). } } . readOnly = arr1.IsReadOnly. Console.IndexOf(arr1.WriteLine("\n"). rank = arr1. rank).Sort(arr1). int len.WriteLine("Fixed Size:\t{0}". readOnly). Console.IsSynchronized.WriteLine("Length:\t{0}". Array.WriteLine("\nElements of array is:\n"). 33. 33)). 0. } static void Main(string[] args) { int[] arr1 = new int[5] { 43.WriteLine("Get Index:\t{0}".Write("\t{0}".WriteLine("Get Value:\t{0}". len). bool fixedSize.IsFixedSize. 5). arr1. } Console.SetValue(99. Console. printArray(arr2). printArray(arr1). Array.

‬‬ ‫‪ SyncHronized‬من النوع ‪ bool‬كما في الشيفرة التالية‪:‬‬ ‫.WriteLine("\n‬‬ ‫}‬ ‫في الشيفرة التالية التي كتبناها قمنا بتعريف مصفوفتين ‪ arr1‬و ‪ arr2‬من نوع ‪ int‬تحوي كل منهما خمس‬ ‫عناصر إال أن المصفوفة ‪ arr1‬قمنا بإسناد قيم العناصر لها ومن ثم قمنا بالتصريح عن متحولين ‪len.} ‪int[] arr1 = new int[5] { 43.)"‪Console. ‫الشكل (‪)5-19‬‬ ‫كيفية العمل‪:‬‬ ‫‪How it Works:‬‬ ‫في البداية قمنا ببناء دالة أو تابع ضمن ‪ Class‬يقوم هذا التابع عند استدعائه بطباعة عناصر المصفوفة‬ ‫وفق ترتيب معين ال تقلق سوف نتعلم هذا األمر في الفصل التالي إن شاء هللا والكود التالي هو لبناء تابع‬ ‫الطباعة ضمن ‪:Class‬‬ ‫‪class Program‬‬ ‫{‬ ‫)‪static void printArray(int[] arr‬‬ ‫{‬ ‫.‬‬ ‫‪ rank‬من النوع ‪ int‬كما صرحنا عن ثالثة متحوالت أخرى ‪fixedSize. 33.WriteLine("\nElements of array is:\n‬‬ ‫)‪foreach (int i in arr‬‬ ‫{‬ ‫.]‪int[] arr2 = new int[5‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪135 -‬‬ ‫‪-‬‬ . i‬‬ ‫}‬ ‫. readOnly. 6‬‬ ‫.Write("\t{0}". 26.)‪Console. 14.)"‪Console.

WriteLine("Read Only:\t{0}".‪len = arr1.)‪Console.)‪Console. SyncHronized‬‬ ‫من ثم عملنا على عكس ترتيب عناصر المصفوفة باستخدام الخاصية ‪ Reverse‬وإعادة ترتيب عناصر‬ ‫المصفوفة تصاعديا باستخدام الخاصية ‪ Sort‬حيث قمنا بطباعة النتيجة باستدعاء دالة الطباعة‬ ‫‪ printArray‬التي بنيناها سابقا في ‪ Class‬كما في الشيفرة التالية‪:‬‬ ‫.Length‬‬ ‫.)‪Console. SyncHronized‬‬ ‫من ثم أسندنا للمتحول ‪ len‬طول المصفوفة ‪ arr1‬باستخدام الخاصية ‪ Length‬كما أسندنا للمتحول ‪rank‬‬ ‫رتبة المصفوفة ‪ arr1‬باستخدام الخاصية ‪ Rank‬كما أسندنا للمتحول المنطقي ‪ fixedSize‬قيمة منطقية‬ ‫باستخدام الخاصية ‪ IsFixedSize‬التي تختبر المصفوفة ‪ arr1‬فإذا كانت ثابتة تعطي القيمة ‪ True‬وإال‬ ‫فإنها تعطي القيمة ‪ False‬ومن ثم أسندنا للمتحول المنطقي ‪ readOnly‬قيمة منطقية باستخدام الخاصية‬ ‫‪ IsReadOnly‬التي تختبر المصفوفة ‪ arr1‬فإذا كانت للقراءة فقط فإنها تعطي القيمة ‪ True‬وإال فإنها‬ ‫تعطي القيمة ‪ False‬وكذلك األمر أسندنا للمتحول المنطقي ‪ SyncHronized‬قيمة منطقية باستخدام‬ ‫الخاصية ‪ IsSynchronized‬التي تختبر أمان التزامن فإذا كان أمن تعطي القيمة ‪ True‬وإال فإنها تعطي‬ ‫القيمة ‪ False‬حيث عملنا على إظهار ناتج المتحوالت الخمسة بعد إسناد القيم لها على شاشة ‪Console‬‬ ‫باستخدام الشيفرة التالية‪:‬‬ ‫. len‬‬ ‫.‪SyncHronized = arr1. readOnly.‬‬ ‫كما قمنا بطباعة نتيجة الخاصية )‪ GetValue(4‬في المصفوفة ‪ arr1‬حيث تعمل هذه الخاصية على‬ ‫إظهار قيمة العنصر ذو الدليل ‪ n‬في مثالنا هذا طلبنا قيمة العنصر ذو الدليل رقم ‪ 4‬أي العنصر رقم ‪ 5‬من‬ ‫المصفوفة فكانت قيمته تساوي ‪ 43‬حاول أن تطلب قيم مختلفة من الدليل الكن انتبه أن الترقيم يبدا من‬ ‫صفر فال تحاول أن تطلب قيمة دليل خارج طول المصفوفة ألن ذلك سوف يؤدي لحدوث خطأ‪.)‪Console.)‪Array.‪int len.)‪printArray(arr1‬‬ ‫من ثم قمنا بطباعة نتيجة بعض خواص المصفوفة ‪ arr1‬منها الخاصية )‪ GetLength(0‬وهي تشبه‬ ‫الخاصية ‪ Length‬إال أننا هنا يمكننا في حالة المصفوفة متعددة األبعاد يمكننا تحديد البعد المراد تحديد‬ ‫طوله وفي حالتنا هنا ال يوجد سوى بعد واحد لذا وضعنا القيمة ‪ 9‬ولو أردنا ان نحدد البعد الثاني في‬ ‫مصفوفة ثنائية البعد لوضعنا الرقم ‪ 1‬وهكذا‪.Rank‬‬ ‫.WriteLine("Rank:\t{0}". fixedSize‬‬ ‫.IsSynchronized‬‬ ‫.WriteLine("Synchronized:\t{0}". readOnly‬‬ ‫.‪rank = arr1.)‪printArray(arr1‬‬ ‫.IsFixedSize‬‬ ‫. 33‬فهي ترجع قيمة الدليل للعنصر ذو القيمة ‪ 33‬من المصفوفة ‪arr1‬‬ ‫والخاصية )‪ GetLongLength(0‬فهي تعطي قيمة طول المصفوفة ‪ arr1‬إال أن الناتج يكون من نوع‬ ‫بيانات ‪ int64‬أما الخاصية )‪ GetLowerBound(0‬فهي تعطي دليل أول عنصر من المصفوفة‬ ‫والخاصية )‪ GetUpperBound(0‬تعطي دليل أخر عنصر من المصفوفة ‪ arr1‬طبعا هاتين الخاصيتان‬ ‫تعطيان قيم تماثل الترقيم الذي تعتمده لغة ‪.‪bool fixedSize. rank‬‬ ‫.‪readOnly = arr1.‪fixedSize = arr1.IsReadOnly‬‬ ‫.WriteLine("Length:\t{0}".)‪Console.)‪Array.‬‬ ‫أما الخاصية )‪ IndexOf (arr1.Reverse(arr1‬‬ ‫.Sort(arr1‬‬ ‫.C#‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪136 -‬‬ ‫‪-‬‬ .WriteLine("Fixed Size:\t{0}". ‫. rank‬‬ ‫.

WriteLine("Get‬‬ ‫. arr1.Clear(arr1.)‪printArray(arr2‬‬ ‫.GetValue(4‬‬ ‫‪Console.)‪Array. arr1. 5‬‬ ‫. arr1.GetType‬‬ ‫في النهاية قمنا باستبدال قيمة أحد عناصر المصفوفة عن طريق تحديد دليله والقيمة الجديدة المراد تخزينها‬ ‫باستخدام الخاصية ‪ SetValue‬كما قمن بنسخ قيم عناصر المصفوفة ‪ arr1‬إلى المصفوفة ‪ arr2‬باستخدام‬ ‫أمر النسخ ‪ Copy‬ز أخير قمن بتصفير قيم المصفوفة ‪ arr1‬باستخدام األمر ‪ Clear‬ومن ثم قمنا بطباعة‬ ‫الخرج لكل األوامر السابقة باستدعاء الدالة ‪ printArray‬كما تبين ذلك الشيفرة التالية‪:‬‬ ‫.WriteLine("Get‬‬ ‫.microsoft.110).GetLongLength(0‬‬ ‫‪Console. arr1.GetUpperBound(0‬‬ ‫‪Console. arr2.WriteLine("Get‬‬ ‫.IndexOf(arr1.SetValue(99.GetLength(0‬‬ ‫‪Console.))‪Length:\t{0}".GetLowerBound(0‬‬ ‫‪Console.)‪arr1. 5‬‬ ‫.WriteLine("Get‬‬ ‫.aspx‬‬ ‫تشبه اللوائح إلى حد كبير المصفوفات إال أن االختالف بينها هو أن المصفوفات تملك حجما ثابتا نقوم‬ ‫باإلعالن عنه أثناء التصريح عن المصفوفة أما اللوائح فإنها متغيرة الحجم أي أنها ديناميكية وبالتالي فإننا‬ ‫لسنا مضطرين لتحديد حجم اللوائح‪.‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪137 -‬‬ ‫‪-‬‬ .WriteLine("Get‬‬ ‫.))(‪Type:\t{0}".))‪LongLength:\t{0}".))‪Index:\t{0}".com/en-us/library/system.WriteLine("Get‬‬ ‫.‬‬ ‫للتوسع في خصائص المصفوفات يمكنك مراجعة مكتبات ‪ msdn‬للغة البرمجة ‪ C#‬على‬ ‫الرابط‪:‬‬ ‫‪http://msdn. arr1. 0‬‬ ‫. arr1. 33‬‬ ‫‪Console.))‪Value:\t{0}".)‪printArray(arr1‬‬ ‫مالحظة‪:‬‬ ‫استخدمنا في هذا التطبيق رمز الجدولة االفقية "‪ " \t‬من أجل تحسين إظهار الطباعة على‬ ‫شاشة ‪ Console‬راجع الفصل الثالث‪.)‪Array.))‪LowerBound:\t{0}".))‪UpperBound:\t{0}". Array.Copy(arr1.‫أما الخاصية )(‪ GetType‬فهي تظهر نوع البيانات المخزنة ضمن المصفوفة ‪ arr1‬والشيفرة التالية تبين‬ ‫طرق إسناد هذه الخواص‪:‬‬ ‫‪Console.WriteLine("Get‬‬ ‫.array_properties(v=vs. 0.

List<string> friendNames = new List<string>().ToInt32(Console. Console.i).WriteLine("My Friend {0}". for (i = 1. } foreach (string friend in friendNames) { Console. friendNames. ‫< تمثل نوع بيانات العناصر ويمكن أن تمثل أي نوع كان سواء كان نوع بسيطا‬baseType> ‫حيث أن‬ .WriteLine("input Numbers of element"). friendName = Convert.friend)."Kaled".‫أما إظهار العناصر فهو مشابه تماما إلظهار العناصر في المصفوفات‬ :‫تطبيق حول استخدام اللوائح‬ . i <= j.)5-29( ‫ فيظهر الشكل‬Ctrl+F5 ‫ نفذ التطبيق بالضغط على مفتاح‬-3 ‫ املهندس حسام الدين الرز‬:‫إعداد‬ 138 - - . . friendName.Add("Kaled"). i++) { Console.ToString(Console. string friendName. .)‫< فتمثل اسم الالئحة (أو اسم متحول الالئحة‬name> ‫أو تعداد أو بنية أما‬ :‫ويمكن إضافة عناصر لالئحة أثناء التصريح كما يلي‬ List<string> friendName = new List<string> {"Ahmad". friendName. j.‫ تحوي على ثالثة أسماء‬friendName ‫ باسم‬string ‫حيث قمنا هنا بالتصريح عن الئحة من النوع‬ :‫ كما في الشيفرة التالية‬Add ‫كما يمكننا إضافة عناصر لها باستخدام الدالة‬ List<string> friendName = new List<string>()."Amen"}.Add("Amen"). :‫يمكننا التصريح عن اللوائح وفقا للصيغة التالية‬ List<BaseType> <name>= new List<Type> ().WriteLine("input Your Friends Name {0}".C# ‫ أضف الشيفرة البرمجية التالية إلى محرر نصوص‬-2 static void Main(string[] args) { int i. } } .Console Lists ‫ جديد باسم‬Console ‫ قم بإنشاء تطبيق‬-1 .ReadLine()).ReadLine()). friendName.Add("Ahmad").Add(friendName). j = Convert.

friend‬‬ ‫}‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪139 -‬‬ ‫‪-‬‬ .)‪Console.ToInt32(Console.29‬‬ ‫كيفية العمل‪:‬‬ ‫‪How it Works:‬‬ ‫في هذا التطبيق قمنا بالتصريح عن متحولين من النوع ‪ int‬وهما المتحولين ‪ i‬و‪ j‬كما صرحنا عن متحول‬ ‫أخر من النوع ‪ string‬باسم ‪ friendName‬وقمنا بالتصريح عن الئحة من النوع ‪ string‬باسم‬ ‫‪ friendNames‬دون أن نحدد عناصر هذه الالئحة كما تبين ذلك الشيفرة التالية‪:‬‬ ‫.))(‪j = Convert. i <= j.)‪Console. ‫الشكل (‪)5.Add(friendName‬‬ ‫}‬ ‫بعد ذلك استخدمنا حلقة ‪ foreach‬من أجل طباعة عناصر الالئحة على نافذة الخرج كما تبين ذلك الشيفرة‪:‬‬ ‫)‪foreach (string friend in friendNames‬‬ ‫{‬ ‫.ReadLine‬‬ ‫)‪for (i = 1.)‪friendNames.)"‪Console.ToString(Console.i‬‬ ‫. i++‬‬ ‫{‬ ‫.WriteLine("input Numbers of element‬‬ ‫.WriteLine("input Your Friends Name {0}".ReadLine‬‬ ‫.WriteLine("My Friend {0}". j‬‬ ‫.))(‪friendName = Convert.)(>‪List<string> friendNames = new List<string‬‬ ‫ومن ثم طلبنا من المستخدم أن يدخل عدد العناصر التي يرغب بإدخالها ضمن الالئحة حيث استخدمنا‬ ‫الرقم المدخل ببناء حلقة تسمح لنا بإدخال العناصر ومن ثم تسند العناصر المدخلة بعد تحويلها إلى النوع‬ ‫‪ string‬إلى الالئحة ‪ friendName‬وذلك باستخدام الشيفرة التالية‪:‬‬ ‫.‪string friendName‬‬ ‫.‪int i.

‫تحتوي اللوائح على بعض الخصائص والدوال التي قد تساعدك في العمل عليها وأشهر هذه الخصائص‬ ‫والدوال وأكثرها استخداما مبين في الجدول التالي‪:‬‬ ‫االستخدام‬ ‫الخاصية أو الدالة‬ ‫تحدد عدد عناصر الالئحة (طول) بعدد صحيح‪. i‬‬ ‫}‬ ‫.)"‪Console.‬‬ ‫‪Capacity‬‬ ‫يحدد نوع عناصر الالئحة‪.‬‬ ‫‪Clear‬‬ ‫تطبيق حول استخدام خصائص ودوال اللوائح‪:‬‬ ‫‪ -1‬قم بإنشاء تطبيق ‪ Console‬جديد باسم ‪.WriteLine("\nElements of List is:\n‬‬ ‫)‪foreach (int i in lists‬‬ ‫{‬ ‫.‬‬ ‫‪Contains‬‬ ‫يقوم بإزالة عنصر من الالئحة عن طريق تحديد دليله‬ ‫‪RemoveAt‬‬ ‫يقوم بمسح مجال من العناصر عن طريق تحديد عرض المجال ونقطة‬ ‫‪RemoveRange‬‬ ‫البداية‪.Write("\t{0}".C#‬‬ ‫‪class Program‬‬ ‫{‬ ‫)‪static void printList(List <int> lists‬‬ ‫{‬ ‫.‬‬ ‫‪GetType‬‬ ‫يقوم بجمع عناصر الالئحة إذا كانت من نوع ‪.Console Lists Properties‬‬ ‫‪ -2‬أضف الشيفرة البرمجية التالية إلى محرر نصوص ‪.‬‬ ‫إلزالة عنصر من الالئحة‬ ‫‪Remove‬‬ ‫يحدد حجم الالئحة‪.WriteLine("\n‬‬ ‫}‬ ‫)‪static void Main(string[] args‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪140 -‬‬ ‫‪-‬‬ .int‬‬ ‫‪Sum‬‬ ‫يقوم باختبار وجود قيمة ما ضمن الالئحة‪.‬‬ ‫يقوم بمسح جميع عناصر الالئحة‪.‬‬ ‫‪add‬‬ ‫يضيف عنصر جديد لالئحة بحيث يحدث إزاحة للعنصر الذي سيحل مكانه‬ ‫‪Insert‬‬ ‫ويأخذ دليله‪.‬‬ ‫‪Count‬‬ ‫تقوم بترتيب عناصر الالئحة تصاعديا إذا كانت رقمية وترتيب هجائي إذا‬ ‫‪Sort‬‬ ‫كانت نصية‪.)"‪Console.)‪Console.‬‬ ‫تقوم بعكس ترتيب عناصر المصفوفة‬ ‫‪Reverse‬‬ ‫يضيف عنصر لالئحة يتوضع في نهاية الالئحة‪.

numbers. numbers. } } . printList(numbers). printList(numbers). Console. printList(numbers).Sort(). Console. numbers. 25. numbers. 8 }.Clear().Reverse(). Console. numbers.GetType()).WriteLine("Get Type:\t{0}".RemoveAt(1). printList(numbers). numbers .Count).)5-21( ‫ فيظهر الشكل‬Ctrl+F5 ‫ نفذ التطبيق بالضغط على مفتاح‬-3 :‫كيفية العمل‬ How it Works: ‫لن أخوض في تفاصيل هذا التطبيق ألنني اجزم بأنك أصبحت قادرا على قراءة الشيفرات لذا سأترك‬ . numbers. 66. 4). printList(numbers). { List<int> numbers = new List<int> { 14. } numbers. 78.Add(96). numbers. 33. Console. 2. printList(numbers).‫األمر لك‬ ‫ املهندس حسام الدين الرز‬:‫إعداد‬ 141 - - .WriteLine("sum element:\t{0}".Capacity). if (numbers. printList(numbers).RemoveRange(2. numbers.Contains (25)) { Console .Sum()). numbers.WriteLine("Get length:\t{0}". printList(numbers). numbers.WriteLine("Get Size:\t{0}".Insert(1.WriteLine ("The Lists contains of 25").Remove(8). 88).

21‬‬ ‫لقد اقتصر استخدامنا للسالسل النصية منذ بداية هذا الكتاب على طباعة هذه السالسل النصية على نافذة‬ ‫الخرج أو قراءة سالسل نصية من دخل المستخدم باإلضافة إلى ضم السالسل النصية مع بعضها بواسطة‬ ‫العامل ‪.+‬‬ ‫ومع تقدم عملية تطويرك للتطبيقات ستحتاج لمعالجات إضافية على السالسل النصية وليس مجرد قراءة‬ ‫وكتابة السالسل النصية من وإلى نافذة ‪ Console‬لقد خصصنا هذا القسم لتناول كيفية معالجة السالسل‬ ‫النصية والتي سنستخدمها بكثرة في البرمجة بلفة ‪ C#‬من خالل الفصول القادمة لهذا الكتاب‪.‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪142 -‬‬ ‫‪-‬‬ . ‫الشكل (‪)5.

myString.)‪Console.‫وكبداية لمناقشتنا هذه من األ فضل أن ننوه إلى أنه يمكننا أن نتعامل مع السلسلة النصية على أنها عبارة‬ ‫عن مصفوفة من الرموز أي يمكننا تمثيل المتحول من نوع ‪ String‬بمصفوفة نوعها األساسي هو ‪char‬‬ ‫هذا يعني أنه يمكننا الوصول إلى رموز السلسلة النصية كال على حدة باستخدام صيغة كما يلي‪:‬‬ ‫.ToCharArray‬فهناك األمر ‪ ToLower‬و ‪ ToUpper‬ومهمتهما تحويل أحرف السلسلة‬ ‫النصية جميعها إلى حروف صغيرة أو كبيرة‪.WriteLine("input any statement‬‬ ‫.ReadLine‬‬ ‫.‬‬ ‫يمكننا أن نستخدم السالسل النصية ضمن حلقات ‪ foreach‬أيضا على سبيل المثال‪:‬‬ ‫) ‪foreach (char character in myString‬‬ ‫{‬ ‫.WriteLine("your input True‬‬ ‫‪else‬‬ ‫.ReadLine‬‬ ‫)"‪if (userResponse.)"‪Console.)(‪Console.) ‪Console.WriteLine("input any statement‬‬ ‫.)"‪Console.ToLower() == "yes‬‬ ‫.)"‪Console .)(‪string myString = Console.)(‪string userResponse = Console.)(‪char[] myChar = myString.ToCharArray‬‬ ‫عندئذ يمكننا أن نعالج مصفوفة ‪ char‬باألسلوب الذي نريد فيمكننا أن نغير في عناصرها ونكتب ضمنها‬ ‫كما نريد‪.‬‬ ‫إن هذين األمرين مهمان جدا ولكي تدرك ذلك لنفترض أن تطبيقنا ينتظر دخال من المستخدم وبناء على‬ ‫هذا الدخل فإن هناك شيفرة برمجية معينة سيتم تنفيذها فلنفترض على سبيل المثال أن المستخدم أدخل‬ ‫السلسلة النصية " ‪ " yes‬عندئذ إذا قمنا بتحويل السلسلة النصية التي أدخلها المستخدم إلى حروف صغيرة‬ ‫فإننا سنتمكن من معالجة الحاالت التي يمكن للمستخدم فيها أن يدخل " ‪ "Yes‬أو "‪ "yeS‬أو "‪ "YES‬وهي‬ ‫حاالت واردة جدا‪:‬‬ ‫."‪string myString = "a String‬‬ ‫.'‪myString[1] = 'a‬‬ ‫ولكي نتمكن من الحصول على مصفوفة ‪ char‬يمكننا الكتابة إليها فإننا سنستخدم األمر‬ ‫)(‪ ToCharArray‬والذي يعيد مصفوفة رموز تمثل مصفوفة رموز تمثل السلسلة النصية‪:‬‬ ‫. character‬‬ ‫.)(‪Console.)(‪Console."‪string myString = "A String‬‬ ‫.ReadLine‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪143 -‬‬ ‫‪-‬‬ .ReadLine‬‬ ‫}‬ ‫وكما في المصفوفات فإنه يمكننا أن نحصل على عدد الرموز المكونة للسلسلة النصية وذلك باستخدام‬ ‫األمر ‪ Length‬كما في المثال التالي‪:‬‬ ‫.ReadLine‬‬ ‫هناك الكثير من التقنيات األساسية لمعالجة السالسل النصية والتي تستخدم أوامر مشابهة لشكل األمر‬ ‫‪ <string>.WriteLine("{0}".)"‪Console.WriteLine("You type {0} characters.Length‬‬ ‫.".]‪char myChar = myString[1‬‬ ‫إن قراءة الرموز بهذه الصورة أمر ممكن ولكن ال يمكننا استخدام هذه الطريقة إلسناد الرموز إلى السلسلة‬ ‫النصية أي أن الشيفرة التالية غير مقبولة‪:‬‬ ‫.WriteLine ("your input False‬‬ ‫.

)(‪string userResponse = Console.)"‪Console.)"‪Console .}'‪char [] trimChars={' '.ToLower() == "yes‬‬ ‫.)"‪Console.)( ‪userResponse =userResponse .)(‪userResponse = userResponse.WriteLine("your input True‬‬ ‫‪else‬‬ ‫.WriteLine("your input True‬‬ ‫‪else‬‬ ‫.ToLower‬‬ ‫تلك هي نقطة هامة جدا يجب أن ننتبه إليها فكتابة الشيفرة التالية‪:‬‬ ‫.)(‪Console.WriteLine("input any statement‬‬ ‫.Trim(trimChars‬‬ ‫)"‪if (userResponse.)"‪Console.ReadLine‬‬ ‫وبهذا يمكننا أن نعالج حاالت إدخال مثل‪:‬‬ ‫" ‪" yes‬‬ ‫"‪" yes‬‬ ‫" ‪"yes‬‬ ‫ويمكننا أن نستخدم هذا األمر إلزالة أية رموز من السلسلة النصية وذلك بواسطة تحديد مصفوفة من نوع‬ ‫‪ char‬كبارامتر لهذا األمر إليك المثال الذي يوضح ذلك‪:‬‬ ‫.WriteLine ("your input False‬‬ ‫.)"‪Console.)(‪string userResponse = Console.)"‪Console.)"‪Console.) ‪userResponse = userResponse.WriteLine("your input False‬‬ ‫.ToLower() == "y‬‬ ‫.ReadLine‬‬ ‫الحظ أن هذا األمر مثله مثل بقية أوامر السالسل النصية ال يغير السلسلة النصية التي نطبق األمر عليها‬ ‫وإنما يحفظ نتيجة األمر في سلسلة نصية أخرى تمثل ناتج تطبيق هذا األمر حيث سنستخدمها لمقارنة ما‬ ‫(كما في الشيفرة السابقة) أو إلسنادها إلى متحول آخر أو ربما إلى نفس المتحول كما في المثال‪:‬‬ ‫.‫لكن إذا افترضنا عدم استخدام مثل هذا األمر عندئذ علينا أن نتأكد من جميع الحاالت التي يمكن للمستخدم‬ ‫أن يدخل الكلمة " ‪ " yes‬عندها تخيل الشيفرة التالية ومدى تعقيدها إذا حاولنا أخذ كافة احتماالت كتابة‬ ‫الكلمة " ‪ "yes‬بعين االعتبار‪:‬‬ ‫.)"‪Console.'e'.ToLower‬‬ ‫.)"‪Console.ToLower‬‬ ‫ال يعني أننا حولنا حروف السلسلة النصية في المتحول ‪ userResponse‬إلى حروف صغيرة‪.‬‬ ‫لنرى ماذا يمكننا أن نقوم به مع السالسل النصية أيضا ماذا لو أن المستخدم قام بوضع فراغات إضافية‬ ‫إلى بداية أو نهاية سلسلة الدخل كأن يكتب مثال‪ " yes ":‬وفي حالة كهذه لن نتمكن من الحصول على‬ ‫اإلجابة ‪ yes‬من المستخدم لحسن الحظ فإن هناك األمر )(‪ Trim‬والذي يمكننا تطبيقه على السلسلة النصية‬ ‫حي ث يقوم باستئصال جميع الفراغات من السلسلة النصية إليك المثال التالي‪:‬‬ ‫.ReadLine‬‬ ‫.'s‬‬ ‫.ReadLine‬‬ ‫.ReadLine‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪144 -‬‬ ‫‪-‬‬ .ReadLine‬‬ ‫== ‪if (userResponse == "yes" || userResponse‬‬ ‫"‪"Yes‬‬ ‫‪|| userResponse == "yEs" || userResponse‬‬ ‫"‪== "yeS‬‬ ‫‪|| userResponse == "YEs" || userResponse‬‬ ‫"‪== "yES‬‬ ‫‪|| userResponse == "YeS" || userResponse‬‬ ‫)"‪== "YES‬‬ ‫.WriteLine("input any statement‬‬ ‫.Trim‬‬ ‫)"‪if (userResponse.WriteLine("your input False‬‬ ‫.)(‪Console.)(‪string userResponse = Console.)(‪Console.WriteLine("input any statement‬‬ ‫.)(‪UserResponse = userResponse.)(‪userResponse.WriteLine("your input True‬‬ ‫‪else‬‬ ‫.

"‪string myString="Hussam‬‬ ‫.'-‬‬ ‫النتيجة هي أن المتحول ‪ myString‬سيحتوي على السلسلة النصية"‪.‫وبهذه الطريقة فإننا سنتخلص من اية رموز زائدة تمت كتابتها بصورة خاطئة إن هذا سيؤدي إلى معالجة‬ ‫حالة إدخال مثل‪:‬‬ ‫"‪"yeeeeeeeeeees‬‬ ‫"‪" y‬‬ ‫'‪"yesssssssssssss‬‬ ‫يمكننا استخدام األمرين )(‪ TrimStart‬و )(‪ TrimEnd‬واللذين سيقومان بالتخلص من الفراغات في‬ ‫بداية أو نهاية السلسلة النصية ويمكن أن يتقبال مصفوفة من الرموز ‪ char‬كبارامتر لها في حال أردنا‬ ‫إزالة رموز معينة من بداية أو نهاية السلسلة النصية‪.PadLeft(10."----Hussam‬‬ ‫هناك العديد من أوامر معالجة السالسل النصية الكثير منها مهم في أوضاع محددة وخاصة سوف نتحدث‬ ‫عن هذه األوامر عندما ن ستخدمها في الفصول القادمة وقبل أن ننتقل إلى تطبيق عملي حول معالجة‬ ‫السالسل النصية فإننا سنستعرض جدوال باألوامر المطبقة على السالسل النصية والتي مرت معنا في هذا‬ ‫الفصل‪:‬‬ ‫الوصف‬ ‫الدالة أو الخاصية‬ ‫يعيد هذا االمر مصفوفة من نوع ‪ char‬تمثل عناصرها الرموز المكونة‬ ‫‪ToCharArray‬‬ ‫للسلسلة النصية‪.myString‬‬ ‫يمكن لهذه المناهج أن تفيدنا في محاذاة السالسل النصية ضمن أعمدة وهو أمر مهم عند وضع سالسل‬ ‫األرقام تحت بعضها البعض‪.‬‬ ‫‪ToUpper‬‬ ‫إزالة أي فراغات من السلسلة النصية ويمكننا استخدام االمر إلزله رموز‬ ‫‪Trim‬‬ ‫محددة من السلسلة النصية‪.PadLeft(10‬‬ ‫ستؤدي هذه الشيفرة إلى وضع أربعة فراغات في بداية الكلمة "‪ "Hussam‬في المتحول ‪.‬‬ ‫إزالة أي فراغات من بداية السلسلة النصية ويمكننا استخدام االمر إلزله رموز‬ ‫‪TrimStart‬‬ ‫محددة من بداية السلسلة النصية إن وجدت‪.‬‬ ‫وكما في األمر )(‪ Trim‬فإن هذين األمرين يتقبالن بارمترا آخر باإلضافة إلى البارامتر‬ ‫>‪ <desiredLength‬أال وهو الرمز الذي نود أن نضعه في المساحة الزائدة للسلسلة النصية بدال من‬ ‫الفراغات على سبيل المثال‪:‬‬ ‫.)'‪myString = myString.‬‬ ‫إزالة أي فراغات من نهاية السلسلة النصية ويمكننا استخدام االمر إلزله رموز‬ ‫‪TrimEnd‬‬ ‫محددة من نهاية السلسلة النصية إن وجدت‪.)‪myString = myString.‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪145 -‬‬ ‫‪-‬‬ .‬‬ ‫تحويل جميع الحروف الالتينية للسلسلة النصية إلى حروف صغيرة‪."‪string myString="Hussam‬‬ ‫.‬‬ ‫‪ToLower‬‬ ‫تحويل جميع الحروف الالتينية للسلسلة النصية إلى حروف كبيرة‪.‬‬ ‫هناك أمران أخرا ن لمعالجة السالسل النصية ويمكننا استخدامهما ألمور متعلقة بالفراغات في السالسل‬ ‫النصية وهما‪ PadLeft() :‬و )(‪ PadRight‬يسمح هذان األمران بإضافة عدد من الفراغات إلى يمين أو‬ ‫يسار السلسلة النصية وذلك إليصال السلسلة النصية إلى طول محدد يمكننا استخدام هذين األمرين كما في‬ ‫المثال التالي‪:‬‬ ‫.‬‬ ‫إضافة عدد من الفراغات إلى يسار السلسلة النصية ويمكننا استخدام األمر‬ ‫‪PadLeft‬‬ ‫إلضافة رمز محدد عدد من المرات إلى يسار السلسلة النصية‪.

‬‬ ‫‪StartsWith‬‬ ‫يعطي قيمة منطقية إذا كان النصين متساويان‪.‬‬ ‫يعطي قيمة منطقية لالستعالم عما إذا كان النص ينتهي بكلمة معينة‪.‫إضافة عدد من الفراغات إلى يمين السلسلة النصية ويمكننا استخدام األمر‬ ‫‪PadRight‬‬ ‫إلضافة رمز محدد عدد من المرات إلى يمين السلسلة النصية‪.‬‬ ‫يعمل هذا األمر على دمج نصين أو كلمتان مع بعض استخدامه مثل استخدام‬ ‫‪Concat‬‬ ‫‪ +‬ويكون الناتج الكلمتين أو النصين معا‪.‬‬ ‫هذا األمر يسمح بالتأكد من وجود نص أو كلمة ضمن نص معين ويعود بقيمة‬ ‫‪Contains‬‬ ‫منطقية إما ‪ True‬أو ‪.‬‬ ‫‪Equals‬‬ ‫يستخدم هذا األمر إلزله نص معين إما بتحديد نقطة البداية فقط أو بتحديد نقطة‬ ‫‪Remove‬‬ ‫البداية والمجال‪.‬‬ ‫‪EndsWith‬‬ ‫يعطي قيمة منطقية لالستعالم عما إذا كان النص يبدأ بكلمة معينة‪.string‬‬ ‫يعود بقيمة صحيحة هي عبارة عن عدد االحرف في المصفوفة‪.‬‬ ‫‪Replace‬‬ ‫يعود هذا األمر بنص جديد من النص القديم وذلك ب تحديد نقطة البداية وممكن‬ ‫تحديد نقطة البداية والنهاية‬ ‫‪Substring‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪146 -‬‬ ‫‪-‬‬ .False‬‬ ‫هذا األمر يعمل على نسخ محتوى سلسلة نصية إلى سلسلة نصية أخرى‪.‬‬ ‫‪Copy‬‬ ‫يعمل هذا األمر على نسخ سلسلة نصية إلى مصفوفة من نوع ‪ char‬وهو‬ ‫يحوي على أربع بارامترات األول ‪( int‬بداية اإلضافة بالنسبة للنص‬ ‫المضاف) والثاني مصفوفة من نوع ‪( char‬يضاف إليها ‪ )string‬والثالث من‬ ‫‪CopyTo‬‬ ‫نوع ‪( int‬بداية اإلضافة بالنسبة للمضاف إليه) والرابع من نوع ‪( int‬نهاية‬ ‫اإلضافة من المضاف)‪.‬‬ ‫يعمل هذ ا األمر على دمج نصين أو كلمتان مع بعض الكن الفرق بينه وبين‬ ‫‪ Concat‬أنه يملك بارمترا يسمح بوضع فاصلة بين النصين أو فاصلة منقوطة‬ ‫‪Join‬‬ ‫أو نقطتين فوق بعض أو أي رمز‪.‬‬ ‫‪Length‬‬ ‫هذا األمر يستخدم للمقارنة بين أكثر من كلمة ويعطي القيمة ‪ 9‬إذا كانت‬ ‫الكلمتان متساويتان ويعطي الرقم ‪ 1‬إذا كانت األولى أكبر من الثانية ويعطي‬ ‫الرقم ‪ 1-‬إذا كانت الثانية أكبر من االولى وهذا األمر حساس لحالة األحرف‬ ‫في اللغة الالتينية يعنى ‪ waled‬ال تشبه ‪ WALED‬ويرجع القيمة ‪ 1-‬ألنه‬ ‫‪Compare‬‬ ‫ي عتبر الحروف الكبيرة أكبر من الحروف الصغيرة أما بالنسبة للحروف‬ ‫العربية فيمكن تجاهل التشكيل والكشيدة يعنى وليــــد تساوى وليد‪.‬‬ ‫يستخدم هذا األمر الستبدال حرف بحرف أو كلمة بكلمة‪.‬‬ ‫يعود بمصفوفة منوع ‪ char‬عبارة عن حروف الكلمة إذا كانت من نوع ‪char‬‬ ‫كما يعود بمصفوفة من نوع ‪ string‬عبارة عن كلمات الجملة منفصلة عن‬ ‫‪Split‬‬ ‫بعضها بفراغ إن كانت من نوع ‪.

Split(simpol).statement. 'd'). Console. Console. Mystr.C# ‫ أضف الشيفرة البرمجية التالية إلى محرر نصوص‬-2 static void Main(string[] args) { string statement = "My Name is". 'l'. 'e'. string name = "Hussam ALdeen ALroz". ‫يعمل هذا األمر في البحث عن حرف أو حروف ويرجع بقيمة عددية وهي‬ ‫مكان الحرف في النص أو أول حرف في الكلمة (لو كنت يبحث عن كلمة‬ IndexOf . name)). 'd' }.WriteLine("This StartsWith 'Hussam' ").WriteLine(reuslt). string search = "Name". string Mystr = "baseem".WriteLine(w). } Console. name1 = string. 'e'.WriteLine(myWord ). char[] simpol = { ' ' }.Join (":".Length.ToString()). bool b = statement.Contains(search) ? true : false. string reuslt = null. Console.ToString().Length-1).Equals(name1. StringComparison. for (int i = 0. string reuslt1 = str. c.OrdinalIgnoreCase) ? true : false. 3).Console String Manipulation ‫ جديد باسم‬Console ‫ قم بإنشاء تطبيق‬-1 .StartsWith("Hussam". myWords = statement.Copy(name).OrdinalIgnoreCase)) { Console.‫كاملة) ويعود بسالب واحد لو غير موجود الحرف أو الكلمة في النص‬ :‫تطبيق حول معالجة النصوص‬ .WriteLine(reuslt2).Replace('e'. foreach (string myWord in myWords) { Console. Mystr. } bool w = name. } if (name1. Console.CopyTo(1. StringComparison. string reuslt2 = str. if (name. Console.Concat(statement.WriteLine("This EndsWith 'ALroz' ").WriteLine(reuslt1).EndsWith("ALroz")) { Console. name)). ‫ املهندس حسام الدين الرز‬:‫إعداد‬ 147 - - . string str = "waleed".WriteLine(b.Remove(2. i < c. 1.WriteLine(string. 'a'. char[] c = new char[] { 'w'. i++) { reuslt += c[i].WriteLine(string. } Console. Console. string[] myWords.WriteLine(name1). string name1 = "HUSSAM ALDEEN ALROZ".

Console.)5-22( ‫ فيظهر الشكل‬Ctrl+F5 ‫ نفذ التطبيق بالضغط على مفتاح‬-3 )5. string reuslt3 = str. ‫ املهندس حسام الدين الرز‬:‫إعداد‬ 148 - - .ToString ()). int index = str1.C# ‫ أضف الشيفرة البرمجية التالية إلى محرر نصوص‬-2 static void Main(string[] args) { string myString = "This is a test. } . string str1 = "private void button click sender EventArgs e".Substring(1.‫به‬ .". 3). Console.22( ‫الشكل‬ :‫كيفية العمل‬ How it Works: ‫سوف اترك لك أيضا أمر التعليق على هذا التطبيق أعتقد أنه بات من السهل عليك قراءته وتفهم ما يقوم‬ .WriteLine(reuslt3).WriteLine(index .Console AutoComplete ‫ جديد باسم‬Console ‫ قم بإنشاء تطبيق‬-1 .IndexOf("click").

23‬‬ ‫‪ -4‬اضغط على المفتاح ‪ s‬دون أن تحرك المؤشر‪ .‪string[] myWords‬‬ ‫‪myWords =myString .)5-24‬‬ ‫الشكل (‪)5-24‬‬ ‫‪ -5‬اضغط على المفتاح ‪ p‬دون ان تحرك المؤشر عندئذ سيتغير موقع التحديد في القائمة المنسدلة إلى‬ ‫بند آخر باسم ‪ split‬وسيظهر تلميح ضمن إطار رمادي بجانب القائمة المنسدلة وبضغطك على‬ ‫مفتاح المسطرة ستالحظ أنه تمت عملية إضافة الكلمة تلقائيا دون أن تكون بحاجة لكتابتها كاملة‪.‬عندئذ سيتغير موقع التحديد في القائمة المنسدلة إلى‬ ‫بند آخر وسيظهر تلميح ضمن إطار رمادي بجانب القائمة المنسدلة كما في الشكل (‪. ‫.)5-23‬‬ ‫ال شكل (‪)5.‬‬ ‫}‬ ‫‪ -3‬الحظ بعد كتابتك للنقطة األخيرة في الشيفرة (أي عند ‪ )myString.‬ستالحظ ظهور قائمة منسدلة‬ ‫كما في الشكل (‪.} ' ' { = ‪char[] separator‬‬ ‫.‬‬ ‫.‬‬ ‫‪ -6‬أكمل الشيفرة والحظ ظهور القائمة المنسدلة وكيف ستساعدك في كتابة الشيفرة بحيث نحصل‬ ‫على الشيفرة البرمجية التالية‪:‬‬ ‫)‪static void Main(string[] args‬‬ ‫{‬ ‫."‪string myString = "This is a test.‪string[] myWords‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪149 -‬‬ ‫‪-‬‬ .} ' ' { = ‪char[] separator‬‬ ‫.

)‪Console.)‪myWords = myString.)5-25‬‬ ‫الشكل (‪)5-25‬‬ ‫أخيرا بعد العديد من التطبيقات المتعددة التي كتبناها بواسطة ‪ Visual Studio‬الحظ ظهور قائمة منسدلة‬ ‫عند كتابة أي أمر ويعود السبب في ذلك إلى تغذية الحس الذكي ( ‪ )interlines‬في فيجوال ستوديو وتوفير‬ ‫الكثير من الجهد و العناء عليك فعند وضع النقطة بعد المتحول ‪ myString‬سيتعرف البرنامج على نوع‬ ‫المتحول وبما أن المتحول من نوع ‪ string‬فسيقوم بعرض جميع األوامر التي يمكننا تطبيقها على السالسل‬ ‫النصية وعند هذه النقطة يمكننا أن نتوقف عن الكتابة ومن ثم تحديد األمر الذي نود باستخدام مفاتيح‬ ‫األسهم إلى أعلى أو أسفل وعند كل تحديد ألمر ما من القائمة المنسدلة سيظهر تلميح ضمن إطار أصفر‬ ‫يعطي شرحا مختصرا عن األمر وعن كيفية استخدامه وماهي البارامترات التي يمكن أن يتقبلها‪.)(‪Console. ‫.Split(separator‬‬ ‫)‪foreach (string word in myWords‬‬ ‫{‬ ‫.‬‬ ‫عندما نبدأ بكتابة المزيد من رموز األمر عند هذه النقطة سينتقل التحديد في القائمة المنسدلة إلى األمر‬ ‫الذي تود الوصول إليه مباشر إن هذه الميزة في فيجوال ستوديو مهمة ومفيدة جدا خصوصا عندما ال‬ ‫نكون متأكدين من صحة كتابة األوامر أو نود التعرف على جميع األوامر التي تتقبلها أنواع محددة من‬ ‫المتحوالت كالمتحوالت من نوع ‪.string‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪150 -‬‬ ‫‪-‬‬ .ReadKey‬‬ ‫}‬ ‫‪ -7‬نفذ التطبيق بالضغط على مفتاح ‪ F5‬فيظهر الشكل (‪.WriteLine(word‬‬ ‫}‬ ‫.

‬‬ ‫وتعرفنا على اللوائح وخواصها وأخير تحدثنا عن معالجة السالسل النصية وتناولنا بعض التقنيات‬ ‫والمبادئ األساسية في ذلك ولقد شرحنا بعضا منها فقط وليس جميعها ويمكنك أن تجرب تلك التي لم‬ ‫نتناولها والتعرف عليها‪.‬‬ ‫لقد تعرفنا على التعدادات ورأينا كيف تمثل أسلوبا ممتازا لتعريف أنواع من المتحوالت ال تقبل إال قيما‬ ‫محددة وكذلك تعرفنا على البنى وعلى كيفية االستفادة منها إلنشاء تراكيب من المتحوالت ضمن متحول‬ ‫واحد كما تعرفنا على المصفوفات بكافة أشكالها إن تلك األنواع رغم كونها معقدة قليال إال أنها مفيدة جدا‬ ‫وضرورية في الكثير من المواضيع‪. ‫الخالصة‪:‬‬ ‫‪Summary:‬‬ ‫لقد استفدنا من معلوماتنا التي حصلنا عليها في الفصول السابقة عن المتحوالت في فصلنا هذا للتعرف‬ ‫على أنواع أخرى أكثر تعقيدا لقد تحدثنا في البداية عن تحويل األنواع باعتبار أننا سنحتاج الستخدام هذه‬ ‫التقنية في مواضيع كثيرة أثناء برمجة التطبيقات‪.‬‬ ‫كما تع رفنا بعد ذلك على خواص هذه المصفوفات وكيف لنا أن نستفيد منها في بناء تطبيقاتنا المختلفة‪.‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪151 -‬‬ ‫‪-‬‬ .

‬‬ ‫ال تزال بنية التطبيقات التي يمكننا تطويرها حتى األن محددة نوعا ما فعلى سبيل المثال قد نحتاج إلى‬ ‫إيج اد القيمة األكبر في مصفوفة وقد نحتاج للقيام بذلك في نقاط مختلفة من البرنامج يمكننا أن ننسخ الشيفرة‬ ‫ذاتها ونلصقها في الموضع الذي نود أن نستخدمها فيه إال أن لذلك مشاكل عدة فإذا اضطررت إلى إحداث‬ ‫تعديل بسيط في هذه الشيفرة فإن عليك أن تقوم بهذا التعديل في عدة أماكن من البرنامج وإذا نسيت تعديل‬ ‫أحد المواضع فإنك قد تحصل على نتائج مخيبة لآلمال هذا باإلضافة إلى الطول الزائد للشيفرة‪.)reusable code‬‬ ‫تجعل التوابع شيفرتنا البرمجية مقروءة أكثر وذلك باعتبار أننا نقوم بتجميع مهام محددة ضمن كتلة برمجية‬ ‫واحدة وعند قيامنا بذلك س يصبح جسم برنامجنا قصير جدا وذلك ألن العمل الحقيقي موزع على كتل‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪152 -‬‬ ‫‪-‬‬ .‬‬ ‫توضيح‪:‬‬ ‫تسمى أنواع محددة من التوابع بالمناهج ( ‪ )methods‬إن لهذا المصطلح معنى خاصا جدا في‬ ‫البرمجة ضمن ‪ .‬‬ ‫على سبيل المثال يمكننا أن نكتب تابعا الحتساب القيمة العظمى في مصفوفة ويمكننا أن نستخدم هذا التابع‬ ‫في أي موضع من الشيفرة واستخدام االسطر البرمجية نفسها في كل مرة وبما أننا نكتب هذه الشيفرة مرة‬ ‫واحدة ونستدعيها عدة مرات فإن أي تعديل على الشيفرة سيؤثر على النتائج متى استخدم هذا التابع إن‬ ‫هذا يعطي انطباعا على الشيفرة القابلة إلعادة االستخدام (‪. ‫الفصل السادس‬ ‫التوابع أو الدوال‬ ‫أن جميع األمثلة البرمجية التي تناولناها حتى االن لم تكن تمثل إال كتلة برمجية واحدة وربما تخلل هذه‬ ‫الكتلة بعض الحلقات لتكرار أسطر معينة من الشيفرة أو بعض التفرع لتنفيذ تعليمات اعتمادا على تحقيق‬ ‫شرط ما لكن إذا كنا بحاجة للقيام بعمليات ما على بياناتنا فإن هذا يعني وضع الشيفرة التي ستقوم بهذه‬ ‫المهمة في الموضع الذي تود لها أن تنفذ عنده‪.NET‬وسوف تتوضح لك األمور أكثر الحقا في القسم التالي من هذا الكتاب لذا‬ ‫سنتجنب استخدام هذا المصطلح هنا‪.‬‬ ‫إن الحل لهذه المشكلة يقضي باستخدام التوابع ( ‪ )functions‬تعرف التوابع في لغة ‪ C#‬بانها عبارة عن‬ ‫كتل من الشيفرة البرمجية التي يمكننا أن ننفذ ها في أي موضع من البرنامج‪.

‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪153 -‬‬ ‫‪-‬‬ .‬سوف نبدأ بتوابع بسيطة بتبادل أية بيانات بينها وبين الشيفرة التي تستدعيها ومن ثم سننتقل إلى‬ ‫استخدام أكثر تقدما للتوابع‪.)return values‬‬ ‫وفي مثالنا السابق يمكننا أن نزود التابع بالمصفوفة كبارامتر حيث سيقوم التابع بالبحث عن القيمة األكبر‬ ‫ومن ثم سنحصل على هذه القيمة على شكل قيمة معادة من هذا التابع‪.‬‬ ‫وأخيرا سنعود إلى موضوع التوابع وسنتحدث عن بعض المواضيع التقدمية المتعلقة بهما‪ :‬التحميل الزائد‬ ‫للتوابع (‪ )function overloading‬والمفوضات ( ‪ )delegates‬واالستدعاء التعاودي (‪)recursion‬‬ ‫يمثل التحميل الزائد للتوابع تقنية تمكننا من توقير توابع عديدة لها االسم نفسه ولكن بتواقيع مختلفة (أي‬ ‫ببارامترات وقيم معادة مختلفة) أما المفوض فهو نوع من المتحوال ت يسمح لنا باستخدام التوابع بصورة‬ ‫غير مباشرة فالمفوض نفسه يمكن استخدامه الستدعاء أي تابع له توقيع محدد مما يعطي إمكانية االختيار‬ ‫من بين توابع عديدة أثناء تنقيذ البرنامج وأما التعاودية فهي استدعاء التابع ضمن شيفرته نفسها أي استدعاء‬ ‫التابع ذاتيا‪.‬فيمكننا أن نزود التوابع بالمعلومات التي ستعمل عليها وفي تلك‬ ‫الحالة تسمى هذه المعلومات بالوسطاء أو البارامترات ( ‪ )parameters‬ويمكننا ان نحصل على النتائج‬ ‫من هذه التوابع وتسمى هذه النتائج بالقيم المعادة ( ‪.)signature‬‬ ‫ثم سنتناول موضوع مدى المتحوالت (‪ )variable scope‬ويشتمل على مفهوم محلية المتحوالت‬ ‫واقتصار استخدامها على مناطق محددة من الشيفرة وهو موضوع هام جدا خصوصا عند تجزئة الشيفرة‬ ‫على توابع متعددة‪.‫برمجية أخرى إن هذا المبدأ مشابه لطي وتوسعة مناطق من الشيفرة في ‪ Visual Studio‬ويعطي ذلك‬ ‫بنية منطقية أكثر لتطبيقنا‪.‬‬ ‫هذا يعني أنه يمكننا أن نستخدم التابع نفسه إليجاد القيمة األكبر ألي مصفوفة خالل البرنامج إن‬ ‫البارامترات والقيمة المعادة للتابع تعرف ما يسمى بتوقيع التابع (‪.‬‬ ‫سننتقل بعد ذلك إلى تناول ميزة إضافية ألنواع البنى ‪ string‬التي رأيناها في الفصل السابق وهي إمكانية‬ ‫تزويد البنى بالتوابع على هيئة أعضاء ضمن تعريف البنية‪.‬‬ ‫بعد ذلك سنلقي نظرة عميقة على تابع مهم جدا في ‪ C#‬أال وهو التابع )( ‪ Main‬سنرى كيف يمكننا أن‬ ‫نستخدم هذا التابع لبناء سلوك لتطبيقنا بحيث يستخدم بارامترات الدخل من سطر األوامر مباشرة (كما في‬ ‫أوامر ‪ )DOS‬وهو ما يمكننا من تمرير المعلومات على التطبيقات أث ناء تنفيذها مباشرة‪.‬‬ ‫ويمكن أن تستخدم التوابع إلنشاء شيفرة متعددة األغراض (‪ )multi-purpose‬بحيث يمكن للتوابع أن‬ ‫تؤدي المهام نفسها على بيانات مختلفة‪ .‬‬ ‫سنتعلم في هذا الفصل كيف نضيف التوابع إلى تطبيقاتنا ومن ثم استدعاء هذه التوابع من ضمن شيفرتنا‬ ‫البرمجية‪ .

Console. :‫تطبيق حول تعريف واستخدام توابع أساسية‬ . } ‫ املهندس حسام الدين الرز‬:‫إعداد‬ 154 - - .WriteLine("Text output from Function.ReadKey().)6.1( ‫الشكل‬ :‫كيفية العمل‬ How it Works: :write () ‫تقوم أسطر الشيفرة الخمسة التالية بتعريف تابع جديد باسم‬ static void write() { Console. } ‫ لتصبح‬Main ‫ في جسم التابع الرئيسي‬C# ‫ أضف الشيفرة البرمجية التالية إلى محرر نصوص‬-9 :‫الشيفرة الكلية بالشكل‬ namespace Console_Defining_and_Using_Functions { class Program { static void write() { Console.ReadKey(). Console. } static void Main(string[] args) { write(). Console.").WriteLine("Text output from Function.)6-1( ‫ فيظهر الشكل‬F5 ‫ نفذ التطبيق بالضغط على مفتاح‬-19 . } } .").ReadKey().Console Defining and Using Functions ‫ جديد باسم‬Console ‫ قم بإنشاء تطبيق‬-7 :class Program ‫ في‬C# ‫ أضف الشيفرة البرمجية التالية إلى محرر نصوص‬-8 class Program { static void write() { Console.").WriteLine("Text output from Function.

‫تقوم الشيفرة الموجودة ضمن التابع )( ‪ write‬بإخراج نص بسيط على نافذة الخرج لن نهتم اآلن بالشيفرة‬ ‫المكتوبة ضمن التابع بقدر ما نحن مهتمين بآلية تعريف واستخدام التوابع‪.‬‬ ‫وكما نوهنا مسبقا فإننا استخدمنا الكلمتين ‪ static‬و‪ void‬لتعريف التابع )( ‪ write‬وهما نفس الكلمتين‬ ‫المستخدمتين لتعريف التابع )( ‪ Main‬تشير الكلمة ‪ static‬إلى مفاهيم متعلقة بالبرمجة كائنية التوجه وهو‬ ‫ما سنتحدث عنه في فصول الحقة من هذا الكتاب وحاليا سنكتفي بالتنويه إلى وجوب وضع هذه الكلمة في‬ ‫جميع التوابع التي سسننشأها في هذا الفصل‪.‬‬ ‫يتضمن تعريف التابع هنا على ما يلي‪:‬‬ ‫‪ ‬كلمتان مفتاحيتان هما ‪ static‬و‪.void‬‬ ‫‪ ‬اسم التابع متبوع بقوسين )( ‪.‬‬ ‫أما كلمة ‪ void‬فهي أبسط مما يمكننا شرحه فهذه الكلمة تشير إلى أن هذا التابع ال يعيد أي قيمة سوف نجد‬ ‫الحقا في هذا الفصل ما سنحتاج لكتابته عندما نريد للتابع أن يعيد قيمة ما‪.write‬‬ ‫‪ ‬كتلة من الشيفرة موضوعة ضمن القوسين "}{"‪.‬‬ ‫مالحظة‪:‬‬ ‫نقصد بشيفرة ‪ C#‬التنفيذية هي شيفرة البرنامج التي يتم تنفيذها مباشرة مثل الشيفرة البرمجية‬ ‫للملفات التنفيذية ذات االمتداد ‪..‬‬ ‫نالحظ أن الشيفرة التي استخدمناها لتعريف التابع )( ‪ write‬مشابهة جدا لشيفرة أخرى في تطبيقاتنا‪:‬‬ ‫)‪static void Main(string[] args‬‬ ‫{‬ ‫‪.exe‬‬ ‫إن االختالف الوحيد بين التابع )( ‪ Main‬والتابع )( ‪ write‬الذي عرفناه للتو (بغض النظر عن الشيفرة‬ ‫الموجودة ضمن التابعين) هو ان التابع )( ‪ Main‬يتضمن بعض الشيفرة ضمن القوسين "()" بعد اسم‬ ‫التابع بينما ال يتضمن تابعنا )( ‪ write‬أي شيء ضمن هذين القوسين هنا هو المكان الذي نعرف ضمنه‬ ‫بارامترات التابع وهو ما سنناقشه بعد قليل‪..‬‬ ‫وبالعودة إلى شيفرة التطبيق نالحظ ان التابع )( ‪ Main‬ال يتضمن إال على سطر برمجي وحيد‪:‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪155 -‬‬ ‫‪-‬‬ ..‬‬ ‫}‬ ‫ويعود ذلك إلى ان جميع الشيفرات البرمجية في أمثلتنا الساب قة كانت تمثل جزءا من تابع وهذا التابع له‬ ‫االسم )( ‪ Main‬وهو يمثل نقطة الدخول (‪ )entry point‬األولى لتطبيقات ‪ Console‬فعند ترجمة شيفرة‬ ‫‪ C#‬لتطبيق ‪ Console‬سيتم تنفيذ الشيفرة الموجودة ضمن تابع نقطة الدخول وذلك باستدعاء هذا التابع‬ ‫داخليا وعند انتهاء تنفيذ هذا التا بع سينتهي التطبيق من العمل إن جميع شيفرات ‪ C#‬التنفيذية يجب أن‬ ‫تحتوي على نقطة دخول‪..

‪string myString‬‬ ‫..‬‬ ‫مالحظة‪:‬‬ ‫إن وجود األقواس "() " حتى ولو كانت خالية ضمن توقيع التابع او استدعائه واجب وإذا‬ ‫حاولت إزالة هذه األقواس فإن الشيفرة لن تترجم‪..‪double multipler = 5. ‫)‪static void Main(string[] args‬‬ ‫{‬ ‫.‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪156 -‬‬ ‫‪-‬‬ ..‬‬ ‫وبناء على ذلك يمكننا وضع صيغة للتوابع التي تعيد قيمة كما يلي‪:‬‬ ‫)(>‪static <returnType><functionType‬‬ ‫{‬ ‫‪.)(‪write‬‬ ‫}‬ ‫ذاك السطر هو السطر الذي يقوم باستدعاء التابع )( ‪ write‬وكما تالحظ فإننا سنكتب ببساطة اسم التابع‬ ‫متبوعا بقوسين من الشكل ")( " وعندما يصل تنفيذ الشيفرة إلى هذا الموضع سيتم تنفيذ الشيفرة الموجودة‬ ‫ضمن التابع )( ‪ write‬وعند االنتهاء منها سيعود التحكم إلى التابع )( ‪ Main‬لما بعد سطر استدعاء التابع‪.void‬‬ ‫‪ ‬استخدام الكلمة ‪ return‬إلنهاء تنفيذ التابع ونقل القيمة المعادة إلى الشيفرة التي استدعت التابع‪.‬‬ ‫إن الطريقة األبسط لتبادل البيانات مع التوابع تقتضي باستخدام قيمة معادة وتعامل التوابع التي تعيد قيما‬ ‫كما تعامل المتحوالت تماما وهذا يعني أن بإمكاننا استخدام التوابع ضمن التعا بير كما نستخدم المتحوالت‬ ‫وسوف نرى ذلك الحقا‪...‪myVale = getVal() * multipler‬‬ ‫إذا أردنا للتابع أن يعيد قيمة فإن علينا القيام بما يلي‪:‬‬ ‫‪ ‬تحديد نوع ال قيمة المعادة وذلك ضمن تصريح أو توقيع التابع مكان الكلمة ‪.‪double myVale‬‬ ‫.3‬‬ ‫.‬‬ ‫على سبيل المثال لنفترض أن لدينا تابعا باسم )(‪ getString‬وهو يعيد سلسلة نصية ما عندئذ يمكننا كتابة‬ ‫شيفرة كما يلي‪:‬‬ ‫.)(‪myString = getString‬‬ ‫ولنفرض أيضا أن لدينا تابعا باستخدام )(‪ getVal‬وهو يعيد قيمة من نوع ‪ double‬عندئذ يمكننا كتابة‬ ‫التعبير الحسابي التالي‪:‬‬ ‫.

‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪157 -‬‬ ‫‪-‬‬ .‬‬ ‫يمكننا أن نكتب تابعا كما يلي مثال‪:‬‬ ‫‪class Program‬‬ ‫{‬ ‫)(‪static double getVal‬‬ ‫{‬ ‫.2‬‬ ‫}‬ ‫فإذا كان ‪ checkVal>=5‬فلن تنفذ تعليمة ‪ return‬أبدا وهو امر غير مسموح به‪.2‬‬ ‫.2‬وذلك بحسب قيمة‬ ‫‪ checkVal‬إن التقييد الوحيد هنا هو أن تعليمة ‪ return‬يجب أن تنفذ قبل الوصول إلى قوس إغالق جسم‬ ‫التابع "} " أي أن الشيفرة التالية غير مقبولة‪:‬‬ ‫‪class Program‬‬ ‫{‬ ‫)(‪static double getVal‬‬ ‫{‬ ‫.‪return 5.>‪return <returnValue‬‬ ‫}‬ ‫يمثل >‪ <returnType‬نوع بيانات القيمة التي سيعيدها التابع ويمكن أن يأخذ أي نوع كان سواء كان‬ ‫نوعا بسيطا مثل ‪ string‬أو ‪ int‬أو نوعا مركبا مثل بنى ‪ struct‬أو تعدادا أما >‪ <returnValue‬فيجب‬ ‫أن تكون من نفس نوع >‪ <returnType‬أو يمكن أن تحول بصورة مطلقة إلى هذا النوع‪.‪double checkVal‬‬ ‫)‪if (checkVal <5‬‬ ‫.‪return 5.‪return 5.2‬‬ ‫}‬ ‫هنا سيتم إعادة قيمة واحدة من القيمتين التي يمكن أن يعيدها التابع (‪4. ‫.‪return 4.‪double checkVal‬‬ ‫)‪if (checkVal <5‬‬ ‫.‬‬ ‫عندما يصل التنفيذ إلى الكلمة ‪ return‬سيعود التحكم إلى الشيفرة المستدعاة مباشرة ولن تنفذ أية شيفرة‬ ‫في التابع بعد هذه التعليمة لكن هذا ال يعني أن تعليمة ‪ return‬ال تتوضع إال في نهاية جسم التابع يمكننا‬ ‫أن نستخدم أي عدد من تعليمات ‪ return‬داخل جسم التابع ويمكن ان يكون هذا االستخدام منطقيا خصوصا‬ ‫ضمن بنى التفرع أو الحلقات ولكن تذكر انه متى تم الوصول إلى هذه التعليمة فسيتوقف التابع عن التنفيذ‬ ‫مباشرة وينتقل إلى النقطة التي تم استدعاءه منها على سبيل المثال‪:‬‬ ‫‪class Program‬‬ ‫{‬ ‫)(‪static double getVal‬‬ ‫{‬ ‫.2‬‬ ‫}‬ ‫إن هذه الشيفرة مقبولة تماما إال أنك لن تستخدم تا بعا إلعادة قيمة معلومة (يمكننا تحقيق ذلك باستخدام‬ ‫المتحوالت الثابتة (أي التي يصرح عنا بالكلمة ‪ ))const‬وإنما سنستخدم التوابع إلعادة نتيجة معالجة ما‬ ‫يقوم التابع بها‪.2‬أو‪ )5.

.‫وكمالحظة أخيرة يمكننا أن نستخدم الكلمة ‪ return‬مع التوابع المصرح عنها بالكلمة ‪ void‬أي التوابع‬ ‫التي ال تعيد قيمة وإذا قمنا بذلك فسيتوقف التابع عن العمل عندما يصادف هذه الكلمة مباشرة لكن في هذه‬ ‫الحالة ال يمكننا ان نضع أي شيء بين الكلمة ‪ return‬والفاصلة المنقوطة التي تليها وإال فسينتج عن ذلك‬ ‫خطا من المترجم‪."،‬‬ ‫‪ ‬الئحة البارامترات مطابقة لالئحة في تصري ح التابع وذلك عند استدعاء هذا التابع حيث يفصل‬ ‫بين كل بارامتر برمز الفاصلة "‪ " ،‬أيضا ولكن دون ذكر النوع‪.‬‬ ‫عندما نود أن نزود التابع ببارامترات أو وسطاء فإن علينا أن نحدد التالي‪:‬‬ ‫‪ ‬الئحة البارامترات التي يتقبلها التابع باإلضافة إلى نوع كل بارامتر على حدة حيث يفصل بين‬ ‫كل بارامتر برمز الفاصلة "‪..‬‬ ‫.‬‬ ‫على سبيل المثال يمكن أن يكون لدينا تابع يقوم باحتساب مساحة مستطيل كما يلي‪:‬‬ ‫‪class Program‬‬ ‫{‬ ‫)‪static double recArea(double height.>‪return <returnValue‬‬ ‫}‬ ‫ويمكننا ان نحدد أي عدد من البارامترات لكل واحدة منها اسم ونوع وتمثل هذه البارامترات متحوالت‬ ‫يمكن الوصول إليها ضمن جسم التابع فقط‪.double width‬‬ ‫{‬ ‫.‬‬ ‫{‬ ‫‪..]‪int maxVal = intArray[0‬‬ ‫)‪for (int i = 1.Length.‬‬ ‫أي أن للتابع ذو البارامترات الصيغة التالية‪:‬‬ ‫)‪static <returnType><functionType>(<parmType> <pramName>.Console Parameters‬‬ ‫‪ -2‬أضف الشيفرة البرمجية التالية إلى محرر نصوص ‪ C#‬في ‪:clas s Program‬‬ ‫‪class Program‬‬ ‫{‬ ‫)‪static int MaxValue(int[] intArray‬‬ ‫{‬ ‫. i++‬‬ ‫{‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪158 -‬‬ ‫‪-‬‬ ...‪return height * width‬‬ ‫}‬ ‫تطبيق حول تبادل البيانات مع التوابع‪:‬‬ ‫‪ -1‬قم بإنشاء تطبيق ‪ Console‬جديد باسم ‪. i < intArray...

i < intArray. 3.)‪int mxVal = MaxValue(myArray‬‬ ‫.]‪int maxVal = intArray[0‬‬ ‫)‪for (int i = 1.]‪maxVal = intArray[i‬‬ ‫}‬ ‫. i++‬‬ ‫{‬ ‫)‪if (intArray[i] > maxVal‬‬ ‫. 6.} ‪int[] myArray = { 1. 2. 0.‪return maxVal‬‬ ‫}‬ ‫لهذا التابع بارامتر وحيد وهو عبارة عن مصفوفة من نوع ‪ int‬باسم ‪ intArray‬ولهذا التابع قيمة معادة‬ ‫أيضا وهي من نوع ‪ int‬إن شيفرة جسم التابع بسيطة وهي عبارة عن خوارزمية إليجاد القيمة األكبر في‬ ‫مصفوفة سيتم أوال تهيئة المتحول ‪ maxVal‬بأول قيمة من المصفوفة ويتم بعد ذلك مقارنة قيمة هذا‬ ‫المتحول مع جميع القيم األخرى في المصفوفة وعندما نجد أن هناك قيمة أك بر من القيمة الحالية للمتحول‬ ‫‪ MaxVal‬سيأخذ هذا المتحول هذه القيمة وستتكرر عملية المقارنة مع القيم المتبقية إلى آخر عنصر في‬ ‫المصفوفة وبالتالي عندما تنتهي الحلقة سيتضمن المتحول ‪ mxValue‬أكبر قيمة في المصفوفة وستعاد‬ ‫هذه القيمة بواسطة تعليمة ‪.return‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪159 -‬‬ ‫‪-‬‬ .Length.)6-2‬‬ ‫الشكل (‪)6.WriteLine("The maximum value in myArray is {0}". mxVal‬‬ ‫}‬ ‫}‬ ‫‪ -3‬نفذ التطبيق بالضغط على مفتاح ‪ Ctrl+F5‬فيظهر الشكل (‪. 5.‪return maxVal‬‬ ‫}‬ ‫)‪static void Main(string[] args‬‬ ‫{‬ ‫.]‪maxVal = intArray[i‬‬ ‫}‬ ‫. ‫)‪if (intArray[i] > maxVal‬‬ ‫. 3.2‬‬ ‫كيفية العمل‪:‬‬ ‫‪How it Works:‬‬ ‫تتضمن هذه الشيفرة التابع الذي يقوم بالمثال الذي تحدثنا عنه في بداية هذا الفصل حيث يتقبل هذا التابع‬ ‫مصفوفة من األرقام كبارامتر ويقوم بإعادة القيمة األكبر في المصفوفة التابع هو )(‪ MaxValue‬وهو‬ ‫كما يلي‪:‬‬ ‫‪class Program‬‬ ‫{‬ ‫)‪static int MaxValue(int[] intArray‬‬ ‫{‬ ‫.)‪Console. 2‬‬ ‫. 9. 8.

double n2) { return n1 . 0. mxVal). number2). div(number1. Sub(number1. number2). 2 }. } static void inpu() { Console. ‫ (الحظ‬int ‫ ذو النوع‬mxVal ‫ إلى المتحول‬MaxValue() ‫بعد ذلك سيتم اسناد القيمة المعادة من التابع‬ :)‫كيف قمنا بتمرير المصفوفة إلى هذا التابع‬ int mxVal = MaxValue(myArray). Console.WriteLine("calcolatur"). 9.‫ وتهيئتها بقيم أولية‬int ‫ فهي تقوم بالتصريح عن مصفوفة عددية من نوع‬Main() ‫أما الشيفرة في التابع‬ :MaxValue() ‫وذلك لتمريرها كبارامتر للتابع‬ int[] myArray = { 1. number2).double n2) { return n1 * n2. dov(number1.Parse(Console.Console function calculator ‫ جديد باسم‬Console ‫ قم بإنشاء تطبيق‬-1 :class Program ‫ في‬C# ‫ أضف الشيفرة البرمجية التالية إلى محرر نصوص‬-2 namespace Console_function_calculator { class Program { static double sum(double n1. Console. 3. } } } ‫ املهندس حسام الدين الرز‬:‫إعداد‬ 160 - - . double number1 = double. :‫تطبيق أخر حول تبادل البيانات مع التوابع‬ . 6. } static double Sub(double n1. 3. 5.ReadLine()). } static double dov(double n1. sum(number1.double n2) { return n1 / n2. double number2 = double. number2)).ReadLine()). } static void Main(string[] args) { inpu().n2. double n2) { return n1 + n2. Console. 8.WriteLine("input first number:").WriteLine("input second number:").Parse(Console. 2. :‫وأخيرا سنقوم بطباعة القيمة األكبر على الخرج بواسطة األمر‬ Console. } static double div(double n1.WriteLine("sum={0}\nsub={1}\ndov={2}\ndiv={3}".WriteLine("The maximum value in myArray is {0}".

‬‬ ‫}‬ ‫فإننا ال يمكننا استدعاء هذا التابع كما يلي‪:‬‬ ‫.)"‪myFunction(2. "Hello‬‬ ‫فلقد حاولنا هنا أن نمرر قيمة من نوع ‪ double‬كبارامتر أول وهو غير مطابق لنوع البارامتر األول في‬ ‫سطر توقيع التابع كما أننا مررنا قيمة من نوع ‪ string‬كبارامتر ثاني وهو غير مطابق لنوع البارامتر‬ ‫الثاني والذي هو من نوع ‪.. ‫‪ -3‬نفذ التطبيق بالضغط على مفتاح ‪ Ctrl+F5‬فيظهر الشكل (‪.)6-3‬‬ ‫الشكل(‪)6.)"‪myFunction("Hello‬‬ ‫فلقد قمنا فقط بتمرير قيمة للبارامتر األول ولم نمرر قيمة للبارامتر الثاني‪.‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪161 -‬‬ ‫‪-‬‬ ..6.double‬‬ ‫كما أنه ال يمكننا كتابة‪:‬‬ ‫.3‬‬ ‫كيفية العمل‪:‬‬ ‫‪How it Works:‬‬ ‫أظن أن المثال سهل القراءة سأترك لك التعليق على التطبيق‪.‬‬ ‫عندما نستدعي تابعا ما فإن علينا مطابقة البارامترات المحددة في سطر تصريح التابع ويسمى بسطر‬ ‫توقيع التابع مع األنواع المحررة إليه ضمن سطر استدعاء التابع إن هذا التطابق يشتمل على تطابق عدد‬ ‫البارامترات المحررة وعلى تطابق األنواع لكل بارامتر وبالتالي إذا كان لدينا تابع بالصورة اآلتية‪:‬‬ ‫‪class Program‬‬ ‫{‬ ‫)‪static void myFunction (string myString.double myDouble‬‬ ‫{‬ ‫‪.

mxVal‬‬ ‫.3.<val1>.<val2>.)‪Console. 3.>‪return <returnValue‬‬ ‫}‬ ‫ويمكننا أن نستدعي هذا التابع كما يلي‪:‬‬ ‫.)(‪Console.‬‬ ‫سوف نتعلم الحقا في هذا الفصل تقنية التحميل الزائد للعوامل والتي تمكننا من االلتفاف حول هذه المشكلة‪..9.‬‬ ‫هناك نوع واحد خاص للبارامترات في لغة ‪ C#‬ويجب أن يأتي هذا البارامتر في نهاية الئحة البارامترات‬ ‫دائما ويعرف بمصفوفة البارامترات (‪ )parameter array‬تسمح مصفوفة البارامترات باستدعاء التوابع‬ ‫بعد تزويدها بعدد متغير من البارامترات ويتم تعريف هذا النوع من البارامترات بواسطة الكلمة ‪. 5..‬‬ ‫بالعودة إ لى التطابق السابق فإن هذا يعني أن التابع )( ‪ MaxValue‬ال يمكن أن يستخدم إال إليجاد القيمة‬ ‫األكبر في مصفوفة من نوع ‪ int‬فقط فإن استبدلنا الشيفرة الموجودة في التابع )( ‪ Main‬بالشيفرة التالية‪:‬‬ ‫)‪static void Main(string[] args‬‬ ‫{‬ ‫.)‪double mxVal = MaxValue(myArray‬‬ ‫.‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪162 -‬‬ ‫‪-‬‬ ..)‪<functionName> (<p1>.5.4‬‬ ‫. ‫إن محاولة استدعاء التابع السابق وفقا لالستدعاءين السابقين سيؤدي إلى حصول خطأ من المترجم‪.‬‬ ‫)>‪params <typeof> [] <name‬‬ ‫{‬ ‫‪.... 9. 8.ReadKey‬‬ ‫}‬ ‫فإن هذا سيؤدي إلى حدوث خطأ باعتبار البارامتر الممرر مختلف عن النوع المعروف في توقيع التابع‪.6. 2...‬‬ ‫تمثل >‪ <val1‬و>‪ <val2‬في هذه الصيغة قيما من النوع >‪ <type‬الذي استخدمناه في تعريف صيغة‬ ‫التابع السابقة ليس هناك أية محدودات لعدد البارامترات التي يمكننا تحديدها هنا والتقييد الوحيد هنا هو‬ ‫أن تكون جميع عناصر مصفوفة البارامترات من نوع واحد كما هو محدد في تصريح التابع ويمكننا أال‬ ‫نضع أية بارامترات بالمرة‪.}‪double [] myArray = { 1.WriteLine("The maximum value in myArray is {0}"..‬‬ ‫تبين الشيفرة التالية صيغة إنشاء تابع يتقبل بارامترات عادية ومصفوفة بارامترات‪:‬‬ ‫‪static <returnType> <functionName> (<p1Type> <p1Name>. 6.3.‬‬ ‫.params‬‬ ‫يمكن لمصفوفة البارامترات أن تمثل طريقة مفيدة لتبسيط شيفرتنا فبدال من تمرير المصفوفات إلى التوابع‬ ‫يمكننا أن نمرر عدة بارامترات من نفس النوع إلى التابع حيث ستعامل هذه البارامترات على شكل عناصر‬ ‫لمصفوفة ضمن التابع‪..

8‬‬ ‫في الحقيقة يمكننا ببساطة أن نستدعي هذا التابع دون تمرير أي بارامتر أو بارامتر واحد أو اثنين أو مئات‬ ‫البارامترات فليس هناك كما قلنا حدود لكمية البارامترات الممررة إلى المصفوفة البارامترية‪.. 9. 8‬‬ ‫..‬‬ ‫}‬ ‫أما شيفرة جسم التابع )( ‪ sumVals‬فستقوم بالمرور على جميع عناصر المصفوفة ‪( vals‬أي على جميع‬ ‫البارامترات الممررة) وستجمع هذه القيم مع بعضها البعض ومن ثم ستعيد ناتج الجمع كقيمة معادة للتابع‬ ‫)( ‪.)‪Console. 2.)‪int sum = sumVals(1.‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪163 -‬‬ ‫‪-‬‬ . 5.‪sum += val‬‬ ‫.Console Parameters2‬‬ ‫‪ -2‬أضف الشيفرة البرمجية التالية إلى محرر نصوص ‪ C#‬في ‪:class Program‬‬ ‫‪class Program‬‬ ‫{‬ ‫)‪static int sumVals(params int[] vals‬‬ ‫{‬ ‫. sum‬‬ ‫}‬ ‫‪ -3‬نفذ التطبيق بالضغط على مفتاح ‪ Ctrl+F5‬فيظهر الشكل (‪.‪return sum‬‬ ‫}‬ ‫)‪static void Main(string[] args‬‬ ‫{‬ ‫..‪int sum = 0‬‬ ‫)‪foreach (int val in vals‬‬ ‫. 2. 9. ‫تطبيق آخر حول تبادل البيانات مع التوابع‪:‬‬ ‫‪ -1‬قم بإنشاء تطبيق ‪ Console‬جديد باسم ‪.WriteLine("summed Values={0}".)6-4‬‬ ‫الشكل (‪)6. 5.4‬‬ ‫كيفية العمل‪:‬‬ ‫‪How it Works:‬‬ ‫لقد عرفنا بارامترا في التابع ‪ sumVals‬باستخدام الكلمة ‪ params‬وذلك لكي يتقبل أي عدد من القيم من‬ ‫النوع ‪( int‬فقط)‪:‬‬ ‫)‪static int sumVals(params int[] vals‬‬ ‫{‬ ‫‪.)‪int sum = sumVals(1.sumVals‬‬ ‫أما التابع )( ‪ Main‬فلقد استدعيناه باستخدام خمسة بارامترات (قيم) رقمية صحيحة‪:‬‬ ‫.

)6.ReadKey‬‬ ‫}‬ ‫أن الخرج سيكون كما في الشكل (‪.)6-5‬‬ ‫الشكل (‪.‪int myNumber = 5‬‬ ‫.WriteLine ("val double={0}".)‪showDouble(myNumber‬‬ ‫.)‪Console.WriteLine("myNumber={0}".WriteLine("myNumber={0}".)‪Console.val‬‬ ‫}‬ ‫لقد قمنا هنا بمضاعفة قيمة البارامتر ‪ val‬في هذا التابع إذا قمنا باستدعاء هذا التابع بالصورة التالية‪:‬‬ ‫)‪static void Main(string[] args‬‬ ‫{‬ ‫.)‪Console .‫إن جميع التوابع التي تعرفنا عليها حتى االن لها بارامترات بالقيمة ( ‪ )value parameters‬إن ما أعنيه‬ ‫بذلك هو أنه عندما استخدمت هذه البارامترات فإنني قمت بتمرير القيمة إلى المتحول المستخدم ضمن‬ ‫التابع وأية تعديال ت على هذا المتحول ضمن التابع لن تؤثر على القيمة الفعلية لهذا البارامتر المحدد في‬ ‫استدعاء التابع على سبيل المثال لنفترض تابعا بقوم بمضاعفة قيمة البارامتر الممرر إليه‪:‬‬ ‫)‪static void showDouble (int val‬‬ ‫{‬ ‫.5‬‬ ‫إن استدعاء التابع )( ‪ showDouble‬مع المتحول ‪ myNumber‬كبارامتر ال يؤثر على قيمة المتحول‬ ‫‪ myNumber‬في التابع )( ‪ Main‬حتى إن تمت مضاعفة قيمة البارامتر الداخلي للتابع أي قيمة البارامتر‬ ‫‪. myNumber‬‬ ‫. myNumber‬‬ ‫.‪val *= 2‬‬ ‫.val‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪164 -‬‬ ‫‪-‬‬ .)(‪Console.

WriteLine ("val double = {0}".WriteLine("myNumber={0}".)(‪Console.)‪showDouble(ref myNumber‬‬ ‫.WriteLine("myNumber = {0}".)(‪Console.)‪Console . myNumber‬‬ ‫.‪int myNumber = 5‬‬ ‫.‪int myNumber = 5‬‬ ‫.‬‬ ‫بدال من هذا التعقيد فإننا سنمرر البارامتر بالمرجع (‪ )by reference‬وهذا يعني أن التابع سيتعامل مع‬ ‫المتحول الممرر له مباشرة وليس مع نسخة منه لها نفس القيمة وبالتالي فإن أي تغيير لهذا المتحول ضمن‬ ‫جسم التابع ستنعكس على قيمة المتحول المستخدم كبارامتر ولكي نتمكن من استخدام بارامترات المرجع‬ ‫فإن علينا وضع الكلمة ‪ ref‬قبل نوع واسم البارامتر في سطر تصريح التابع كما يلي‪:‬‬ ‫)‪static void showDouble (ref int val‬‬ ‫{‬ ‫.‪val *= 2‬‬ ‫.)6-6‬‬ ‫الشكل (‪)6.6‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪165 -‬‬ ‫‪-‬‬ .ReadKey‬‬ ‫}‬ ‫والخرج في هذه الحلة سيصبح كما في الشكل (‪.)‪myNumber = showDouble(myNumber‬‬ ‫.WriteLine("myNumber={0}".)‪Console. myNumber‬‬ ‫.)‪Console.‫حسنا ماذا لو أردنا أن تتغير قيمة المتحول ‪ myNumber‬نتيجة لتغير قيمته عندما مررناه إلى التابع‬ ‫عندئذ علينا أن نحول التابع السابق إلى تابع يستطيع أن يعيد قيمة من نوع ‪ int‬ونكتب شيفرة كما يلي‪:‬‬ ‫)‪static void Main(string[] args‬‬ ‫{‬ ‫.val‬‬ ‫}‬ ‫و يجب أن نشير إلى ذلك أيضا ضمن سطر استدعاء التابع كما يلي‪:‬‬ ‫)‪static void Main(string[] args‬‬ ‫{‬ ‫.)‪Console.WriteLine("myNumber = {0}". myNumber‬‬ ‫.ReadKey‬‬ ‫}‬ ‫إن هذه شيفرة غير مريحة وسيزداد األمر تعقيدا إذا كان التابع يعيد قيمة ما في األساس مختلفة عن قيمة‬ ‫البارامتر ‪ val‬ونحن نعلم أن التابع ال يعيد إال قيمة واحدة فقط‪.)‪Console. myNumber‬‬ ‫.

‬‬ ‫وكمثال على ذلك لنفترض تنفيذ التابع )( ‪ MaxValue‬الذي يعيد أكبر قيمة في مصفوفة والذي تناولناه‬ ‫مسبقا سنقوم بتعديل هذا التابع قليال بحيث يعطينا دليل العنصر ذو القيمة األعلى ضمن المصفوفة ولتبسيط‬ ‫األمور فإننا سنقوم بإيجاد دليل أول عنصر له القيمة األعلى وذلك في حال وجود قيمتين تمثالن القيمة‬ ‫العليا في المصفوفة‪. myNumber‬‬ ‫.ReadKey‬‬ ‫}‬ ‫باإلضافة لتمرير القيم بالمرجع يمكننا أن نخصص بارامترا ما على أنه بارامتر خرج باستخدام الكلمة‬ ‫‪ out‬وتستخدم هذه الكلمة تماما مثل الكلمة ‪( ref‬كمقيد للبارامتر في سطر التصريح عن التابع وفي سطر‬ ‫استدعاء التابع أيضا) لبارامترات الخرج سلوك مشابه لسلوك بارامترات المرجع حيث أن قيمة‬ ‫البارامترات ستعاد إلى المتحول المستخدم في استدعاء التابع عند االنتهاء من تنفيذ التابع في الحقيقة هناك‬ ‫اختالفات مهمة بين بارامترات الخرج وباروم ترات المرجع فبينما من غير المقبول استخدام متحول غير‬ ‫مهيئ لم تسند إليه قيمة محددة كبارامتر مرجعي إال أنه يمكننا استخدام متحول غير مهيئ كبارامتر خرج‬ ‫وباإلضافة إلى ذلك فإننا يجب أن نتعامل مع بارامتر الخرج على أساس أنه ليست هناك قيمة مسندة إليه‬ ‫وذلك بالنسبة لل تابع الذي سيستخدمه هذا يعني أنه على الرغم من إمكانية استخدام متحول له قيمة مسندة‬ ‫إليه كبارامتر خرج إال أن القيمة المخزنة في هذا البارامتر ستفقد عند تنفيذ التابع وستتوقع تغيرا لقيمته‪. myNumber‬‬ ‫.WriteLine("myNumber={0}". myNumber‬‬ ‫.)(‪Console.)‪Console.)‪Console. myNumber‬‬ ‫.)‪Console.showDouble‬‬ ‫هناك محددات حول المتحوالت المستخدمة كبارامترات مرجعية أوال يمكن أن تخضع القيمة الممررة‬ ‫بالمرجع لتعديل ما ضمن التابع وبالتالي ال يمكننا أن نمرر متحوال ثابتا كبارامتر مرجعي إلى التابع أي‬ ‫أن الشيفرة التالية غير مقبولة‪:‬‬ ‫)‪static void Main(string[] args‬‬ ‫{‬ ‫.ReadKey‬‬ ‫}‬ ‫ثانيا علينا أن نستخدم متحوال متهيئا فال تسمح لغة ‪ C#‬بافتراض أن بارامتر المرجع سيهيئ في التابع‬ ‫الذي يستخدمه أي أن الشيفرة التالية غير مقبولة أيضا‪:‬‬ ‫)‪static void Main(string[] args‬‬ ‫{‬ ‫.‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪166 -‬‬ ‫‪-‬‬ .)‪showDouble(ref myNumber‬‬ ‫.WriteLine("myNumber={0}".)(‪Console.‪const int myNumber = 5‬‬ ‫.WriteLine("myNumber={0}".)‪showDouble(ref myNumber‬‬ ‫.‪int myNumber‬‬ ‫.WriteLine("myNumber={0}".)‪Console. ‫لقد تغيرت قيمة المتحول ‪ myNumber‬هذه المرة من قبل التابع )( ‪.

:‫للقيام بذلك سنضيف بارامتر خرج بتعديل التابع كما يلي‬
static int MaxValue(int[] intArray, out int maxIndex)
{
int maxVal = intArray[0];
maxIndex = 0;
for (int i = 1; i < intArray.Length; i++)
{
if (intArray[i] > maxVal)
{
maxVal = intArray[i];
maxIndex = i;
}
}
return maxVal;
}

:‫وسنستخدم هذا التابع بالصورة التالية‬
static void Main(string[] args)
{
int[] myArray = { 1, 8, 3, 6, 2, 5, 9, 3, 0, 2 };
int maxIndex;
Console.WriteLine("The maximum value in myArray is {0}",
MaxValue(myArray, out maxIndex));
Console.WriteLine("The first occurrence of this value is at"
+ "element {0}", maxIndex + 1);
Console.ReadKey();
}

.)6-7( ‫والخرج سيكون كما في الشكل‬

.)6- 7( ‫الشكل‬

:‫مالحظة‬
‫ التي سيتم عرضها على الشاشة وذلك كي نحصل‬maxIndex ‫ إلى القيمة‬1 ‫الحظ أنني أضفت‬
‫على الموقع المنطقي للعنصر ذو القيمة األكبر فإذا كان العنصر األكبر هو العنصر األول فإن ما‬
.0 ‫ وليس العنصر رقم‬1 ‫سيطبع هو العنصر رقم‬

‫ املهندس حسام الدين الرز‬:‫إعداد‬
167 -
-

‫ربما تساءلت خالل القسم السابق من هذا الفصل عن ضرورة تبادل البيانات مع التوابع السبب في ذلك‬
‫يعود إلى أن المتحوالت في ‪ C#‬ال يمكن الوصول إليها إال ضمن مناطق محددة ومحلية في الشيفرة‬
‫وبالتالي فإن ما نقصده بمدى المتحول (‪ )Scope‬هو المنطقة التي يمكننا أن نقرأ ونسند القيم من وإلى هذا‬
‫المتحول ضمن شيفرة التطبيق‪.‬‬
‫إن موضوع مدى المتحوالت مهم جدا ومن األفضل أن نتناول هذا الموضوع مع بعض األمثلة‪.‬‬
‫تطبيق حول تعريف واستخدام تابع بسيط‪:‬‬
‫‪ -1‬قم بإنشاء تطبيق ‪ Console‬جديد باسم ‪.Console Defining and Using Functions2‬‬
‫‪ -2‬أضف الشيفرة البرمجية التالية إلى محرر نصوص ‪ C#‬في ‪:class Program‬‬
‫‪class Program‬‬
‫{‬
‫)(‪static void Write‬‬
‫{‬
‫;)‪Console.WriteLine("myString={0}", myString‬‬
‫}‬
‫)‪static void Main(string[] args‬‬
‫{‬
‫;")(‪string myString = "String defined in Main‬‬
‫;)(‪Write‬‬
‫}‬
‫}‬

‫‪ -3‬ترجم الش يفرة والحظ رسالة الخطأ والتحذير التي ستظهر في الئحة المهام الشكل (‪.)6-8‬‬

‫الشكل (‪)6- 8‬‬

‫كيفية العمل‪:‬‬
‫‪How it Works:‬‬
‫أين الخطأ في الشيفرة السابقة؟ حسنا إن المتحول ‪ myString‬معرف ضمن التابع )( ‪ Main‬وال يمكن‬
‫الوصول إلى هذا المتحول ضمن التابع )( ‪.Write‬‬

‫إعداد‪ :‬املهندس حسام الدين الرز‬
‫‪168 -‬‬
‫‪-‬‬

‫يعود السبب في ذلك إلى أن الوصولية إلى هذه المتحوالت لها مدى يحدد المنطقة التي يمكن أن نصل‬
‫ضمن حدودها إلى تلك المتحوالت إن هذا المدى متعلق بكتلة الشيفرة التي تم التصريح عن المتحول‬
‫ضمنها وألي كتل معششة ضمن هذه الكتلة وبالنسبة للتوابع فإن كتل شيفرتها منفصلة عن بعضها البعض‪.‬‬
‫وبالتالي فإن المتحول ‪ myString‬بالنسبة للتابع )( ‪ Write‬هو متحول غير مصرح عنه فهذا المتحول‬
‫مصرح عنه ضمن التابع )( ‪ Main‬وبالتالي ال يمكن الوصول إلى هذا المتحول إال ضمن جسم التابع‬
‫)( ‪ Main‬فقط‪.‬‬
‫في الحقيقة يمكن أن يكون لدينا متحول باسم ‪ myString‬مختلفة تماما عن المتحول ‪ myString‬المصرح‬
‫عنه في التابع )( ‪ Main‬حاول تعديل الشيفرة السابقة إلى الشكل التالي‪:‬‬
‫‪class Program‬‬
‫{‬
‫)(‪static void Write‬‬
‫{‬
‫;")(‪string myString = "String defined in Write‬‬
‫;)")(‪Console.WriteLine("Now in Write‬‬
‫;)‪Console.WriteLine("myString={0}", myString‬‬
‫;)"‪Console.WriteLine("Text outPut from function‬‬
‫}‬
‫)‪static void Main(string[] args‬‬
‫{‬
‫;")(‪string myString = "String defined in Main‬‬
‫;)(‪Write‬‬
‫;)")(‪Console.WriteLine("\n Now in Main‬‬
‫;)‪Console.WriteLine("myString={0}", myString‬‬
‫}‬
‫}‬

‫ستترجم هذه الشيفرة بصورة سليمة وستعطي خرجا كما في الشكل (‪:)6-9‬‬

‫الشكل (‪)6- 9‬‬
‫إن العمليات التي تمت في هذه الشيفرة هي كاآلتي‪:‬‬
‫‪ ‬تعريف وتهيئة متحول من نوع ‪ string‬باسم ‪ myString‬ضمن التابع )( ‪.Main‬‬
‫‪ ‬نقل التحكم من التابع )( ‪ Main‬إلى التابع )( ‪ Write‬وذلك باستدعاء هذا التابع‪.‬‬
‫‪ ‬تعريف وتهيئة متحول من نوع ‪ string‬باسم ‪ myString‬ضمن التابع )( ‪ Write‬ومتحول مختلف‬
‫تماما عن المتحول المصرح عنه في التابع )( ‪.Main‬‬

‫إعداد‪ :‬املهندس حسام الدين الرز‬
‫‪169 -‬‬
‫‪-‬‬

‫ المعرف في التابع‬myString ‫ تتضمن قيمة المتحول‬Console ‫ طباعة سلسلة نصية على نافذة‬
.Write ()
.Write () ‫ بسبب الوصول إلى نهاية التابع‬Main () ‫ إلى التابع‬Write () ‫ نقل التحكم من التابع‬
‫ المعرف في التابع‬myString ‫ تتضمن قيمة المتحول‬Console ‫ طباعة سلسلة نصية على نافذة‬
.Main ()
Local ( ‫تسمى المتحوالت التي يقتصر مداها على التوابع المعرفة ضمنها بالمتحوالت المحلية‬
‫) بحيث يغطي مداها توابع‬global variables ( ‫) ومن الممكن أن يكون لدينا متحوالت عامة‬variables
:‫عدة عدل الشيفرة كما يلي‬
class Program
{
static string myString;
static void Write()
{
string myString = "String defined in Write()";
Console.WriteLine("InNow in Write()");
Console.WriteLine("myString={0}", myString);
Console.WriteLine("Local myString ={0}",myString );
Console.WriteLine("Global myString={0}", Program.myString);
}
static void Main(string[] args)
{
string myString = "String defined in Main()";
Program.myString = "Global string";
Write();
Console.WriteLine("\n Now in Main()");
Console.WriteLine("Local.myString={0}", myString);
Console.WriteLine("Global myString={0}", Program.myString );
}
}

.)6-19( ‫والخرج سيكون كما في الشكل‬

)6- 19( ‫الشكل‬

‫ أيضا لكن هذه المرة صرحنا عن هذا المتحول في أعلى‬myString ‫لقد أضفنا هنا متحوال جديدا باسم‬
:‫هرمية التطبيق وذلك خارج أية توابع‬
static string myString;

‫ املهندس حسام الدين الرز‬:‫إعداد‬
170 -
-

‪int i‬‬ ‫)‪for (i = 0.‬‬ ‫لقد حددنا قيمة للمتحول العام في التابع )( ‪:Main‬‬ ‫.myString‬‬ ‫قد تتساءل األن عن الدا عي الستخدام المتحوالت العامة لتبادل البيانات مع التوابع وذلك بدال من تمرير‬ ‫البارامترات على هذه التوابع كما رئينا ذلك مسبقا هناك حاالت نحتاج إليها بالفعل إلى هذه الطريقة لتبادل‬ ‫البيانات مع التوابع إال أن هناك الكثير من الحاالت إن لم تكن معظمها التي ال تتطلب استخدام هذه التقنية‬ ‫لتبادل البيانات بين التوابع المشكلة مع المتحوالت العامة هي أنها غير مناسبة للتوابع ذات األغراض‬ ‫العامة والتي يمكنها التعامل مع أية بيانات تزودها بها وليست محدودة بالبيانات في المتحوالت العامة‬ ‫سوف نتحدث عن هذه النقطة بتفصيل أكبر الحقا في هذا الفصل‪.myString‬فعندما يكون لدينا متحول محلي له اسم مطابق‬ ‫السم متحول عام عندئذ سيحجب المتحول العام ضمن مدى المتحول المحلي هذا‪.ToString(i‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪171 -‬‬ ‫‪-‬‬ .static‬‬ ‫ولكي نفرق بين هذا المتحول والمتحوالت المحلية ذات االسم ‪ myString‬نفسه المعرفة ضمن التابعين‬ ‫)(‪ Write‬و )(‪ Main‬فإننا سنكتب اسم المتحول الكامل (لقد تحدثنا عن ذلك في الفصل الثالث عند حديثنا‬ ‫عن فضاءات األسما ء) لقد قمنا هنا باإلشارة إلى متحول عام باسم ‪ Program."‪Program.‬‬ ‫لقد ذكرنا مسبقا أن مدى المتحوالت يقتصر على كتلة الشيفرة التي تم التصريح عن المتحول ضمنها وما‬ ‫تتضمن هذه الكتلة من كتل أخرى معششة ضمنها إن ذلك مطبق أيضا على كتل الشيفرة األخرى مثل بنى‬ ‫التفرع والحلقات لنأخذ الشيفرة التالية مثال‪:‬‬ ‫)‪static void Main(string[] args‬‬ ‫{‬ ‫.WriteLine("Global myString={0}".myString‬الحظ أن هذه‬ ‫التسمية ضرورية فقط في الحالة التي نواجه فيها تضاربا بين أسماء المتحوالت العامة والمتحوالت المحلية‬ ‫– كما في حالتنا هنا – فإن لم تكن هناك متحوالت محلية باسم ‪ myString‬في الكتلة البرمجية فيمكننا أن‬ ‫نشير إلى المتحول العام ضمن هذه الكتلة بمجرد ذكر االسم ‪ myString‬دون ذكر الصنف الذي يتبع له‬ ‫هذا المتحول (أي دون كتابة ‪ )Program. i < 10.‫الحظ أننا استخدمنا الكلمة ‪ static‬هنا أيضا للتصريح عن المتحوالت كما استخدمناها للتصريح عن التوابع‬ ‫لقد قلت إنني لن أتحدث عن هذه الكلمة اآلن ولكن يكفي أن أقول إننا يجب أن نضع إما ‪ static‬او ‪const‬‬ ‫بالنسبة للمتحوالت العامة في تطبيقات ‪ Console‬كهذه فإذا أردنا أن نستخدم متحوال ذو قيمة ثابتة (ال‬ ‫يمكن أن تتغير وإن حاولنا تغييرها فسيحدث خطأ) فإننا سنستخدم الكلمة ‪ const‬بدال من ‪.myString = "Global string‬‬ ‫ولقد تمكنا من الوصول إلى هذا المتحول العام ضمن التابع )( ‪:Write‬‬ ‫.)‪String text = "Line:" + Convert.) ‪Console. Program. i++‬‬ ‫{‬ ‫.

)‪Console.WriteLine(text‬‬ ‫}‬ ‫. ‫. text‬‬ ‫}‬ ‫ستنفذ هذه الشيفرة دون أخطاء هذه المرة وناتج تنفيذ هذه الشيفرة كما في الشكل (‪:)6-11‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪172 -‬‬ ‫‪-‬‬ .‪int i‬‬ ‫.)‪Console." "=‪String text‬‬ ‫)‪for (i = 0.WriteLine(text‬‬ ‫}‬ ‫.‬‬ ‫لنعدل الشيفرة السابقة كما يلي‪:‬‬ ‫)‪static void Main(string[] args‬‬ ‫{‬ ‫. i < 10. text‬‬ ‫}‬ ‫سوف تخفق هذه الشيفرة أيضا والسبب هو أن علينا أن نصرح عن المتحوالت وأن نهيئها قبل استخدامها‬ ‫والمتحول ‪ text‬تمت تهيئته ضمن حلقة ‪ for‬فقط فإن القيمة المسندة إلى المتحول ‪ text‬ستفقد عند الخروج‬ ‫من الحلقة‪.ToString(i‬‬ ‫.‪int i‬‬ ‫. i++‬‬ ‫{‬ ‫.)‪Console. i++‬‬ ‫{‬ ‫.WriteLine("Last text output in loop:{0}".)‪text = "Line:" + Convert.WriteLine‬الموجود خارج الحلقة بمحاولة قراءة قيمة المتحول ‪text‬‬ ‫وهو متحول واقع خارج المدى وذلك ألن مدى المتحول ‪ text‬هنا مقتصر على الحلقة فقط‪. text‬‬ ‫}‬ ‫إن المتحول ‪ text‬هنا يمثل متحوال محليا بالنسبة لحلقة ‪ for‬إن هذه الشيفرة لن تترجم وذلك ألننا نقوم في‬ ‫استدعائنا لألمر )(‪ Console.WriteLine(text‬‬ ‫}‬ ‫.)‪Console.WriteLine("Last text output in loop:{0}". i < 10.WriteLine("Last text output in loop:{0}".‪String text‬‬ ‫)‪for (i = 0.)‪text = "Line:" + Convert.‬‬ ‫لنعدل الشيفرة اآلن بالصورة التالية‪:‬‬ ‫)‪static void Main(string[] args‬‬ ‫{‬ ‫.)‪Console.)‪Console.ToString(i‬‬ ‫.

‬‬ ‫ولحسن الحظ فإن مترجم ‪ C#‬سيكتشف مشاكل مدى المتحوالت وسيتجاوب مع رسائل الخطأ التي يولدها‬ ‫نتيجة لذلك وهو ما سيساعدك في الحقيقة لفهم موضوع مدى المتحوالت‪. i++‬‬ ‫إن المتحول ‪ i‬هنا هو متحول محلي لكتلة الحلقة وهذا أمر طبيعي باعتبار أنه من النادر أن نستخدم متحول‬ ‫الحلقة في كتلة برمجية خارج الحلقة‪.11‬‬ ‫الحظ إمكانية الوصول من خارج الحلقة إلى القيمة األخيرة التي أسندت إلى المتحول ‪ text‬ضمن الحلقة‬ ‫إن نتيجة عدم تنفيذ الشيفرة التي تسبق هذه األخيرة يعود إلى حجز الذاكرة للمتحول ‪ text‬أو ألي متحول‬ ‫كان في الحقيقة إن مجرد التصريح عن متحول من نوع بسيط ال يعني حدوث الكثير وإنما عندما يتم إسناد‬ ‫القيم إلى المتحول فإن هذه القيم ستخزن في مكان ما من الذاكرة وعندما يستخدم هذا الجزء من الذاكرة‬ ‫ضمن الحلقة ستعرف هذه القيمة أنها محلية بالنسبة للحلقة وستخرج هذه القيمة عن المدى عند الخروج‬ ‫من جسم الحلقة وحتى إن كان المتحول غير محلي فإن قيمته محلية بينما يضمن لنا إسناد قيمة خارج‬ ‫الحلقة من أن هذه القيمة محلية بالنسبة للشيفرة الرئيسية وهذا يعني أن كتلة الحلقة ستستخدم نفس موقع‬ ‫الذاكرة الذي استخدم لتهيئة المتحول بالقيمة األولية لتخزين قيم المتحول ‪ text‬ولذا فإننا سنتمكن من‬ ‫الوصول إلى هذه القيمة خارج الحلقة‪.‬‬ ‫وكمالحظ أخيرة فإننا ننصح بالتصريح عن جميع المتحوالت وتهيئتها أيضا قبل أن نستخدمها في أي كتلة‬ ‫برمجية واالستثناء الوحيد لذلك هو عندما نصرح عن متحوالت الحلقات كجزء من كتلة الحلقة كما في‬ ‫المثال‪:‬‬ ‫)‪for (int i = 0.‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪173 -‬‬ ‫‪-‬‬ . ‫الشكل (‪)6. i < 10.‬‬ ‫مالحظة‪:‬‬ ‫في الحقيقة إن أكثر األخطاء البرمجية الشائعة التي يقع فيها المبرمجون المبتدئون بلغة ‪C#‬‬ ‫مشابهة للسيناريو السابق لذا يجب عليك استيعاب مفهوم مدى المتحوالت جيدا‪.

‪val = 5‬‬ ‫.‪val *= 2‬‬ ‫.val‬‬ ‫.)( ‪Console .WriteLine("val={0}".‪val *= 2‬‬ ‫.WriteLine("val={0}".val‬‬ ‫}‬ ‫}‬ ‫والشيفرة التالية‪:‬‬ ‫‪class Program‬‬ ‫{‬ ‫.)‪showDouble(ref val‬‬ ‫.‬‬ ‫وكبداية فإننا نذكر بأننا قلنا ان إصدارة التابع )( ‪ showDouble‬التي تستخدم قيمة عامة لن تستخدم إال‬ ‫متحوال واحدا فقط وهو المتحول ‪ val‬دائما وبناء على ذلك فإن علينا أن نستخدم هذا المتحول العام في كل‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪174 -‬‬ ‫‪-‬‬ .WriteLine ("val={0}".‫سوف نلقي في هذا القسم نظرة عميقة على تبادل البيانات ضمن التوابع عبر البيانات العامة وعبر‬ ‫البارامترات والقيم المعادة ولإليجاز سنناقش الفرق بين شيفرة كاآلتية‪:‬‬ ‫‪class Program‬‬ ‫{‬ ‫)‪static void showDouble(ref int val‬‬ ‫{‬ ‫.WriteLine ("val={0}".‪int val = 5‬‬ ‫. val‬‬ ‫}‬ ‫)‪static void Main(string[] args‬‬ ‫{‬ ‫. val‬‬ ‫.)‪Console .)‪Console .WriteLine("val doubled={0}".)‪Console. val‬‬ ‫.‬‬ ‫واآلن ليست هناك أبه قواعد أو أمور إجبارية تضطرك الستخدام طريقة بدال من األخرى وكال التقنيتين‬ ‫المستخدمتين صحيحتان تمام إال أن هناك بعض النقاط الرئيسية التي يجب التنويه عنها هنا‪.)(‪showDouble‬‬ ‫.)‪Console.‪static int val‬‬ ‫)(‪static void showDouble‬‬ ‫{‬ ‫.WriteLine("val doubled={0}". val‬‬ ‫}‬ ‫)‪static void Main(string[] args‬‬ ‫{‬ ‫.)‪Console.)‪Console.ReadKey‬‬ ‫}‬ ‫}‬ ‫إن نتيجة تنفيذ هاتين الشيفرتين متطابقة تماما‪.

‫مرة نود تنفيذ التابع )( ‪ showDouble‬إن هذا يؤثر على تعددية االستخدام للتابع )(‪showDouble‬‬ ‫قليال ويعني أن علينا أن ننسخ قيمة المتحول العام ‪ val‬إلى متحوالت أخرى إذا أردنا أن نحتفظ بالنتائج‬ ‫وباإلضافة إلى ذلك يمكن للبيانات العامة الموجودة في المتحول ‪ val‬أن تعدل في مكان آخر من التطبيق‬ ‫مما يمكن أن يؤدي إلى نتائج غير متوقعة‪.DOS‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪175 -‬‬ ‫‪-‬‬ . out val2‬فإن هذا يعني أن المتحولين ‪ val1‬و ‪ val2‬هما المتحوالن األكثر‬ ‫أهمية في هذا التابع وأن المتحول ‪ val2‬سيأخذ قيمة جديدة عند االنتهاء من تنفيذ التابع وبالعكس فإن لم‬ ‫يستخدم هذا التابع أية بارامترات فإن ذلك سيضطرنا إلى تخمين أي شيء حول البيانات التي ستعالج‬ ‫ضمن التابع‪.‬‬ ‫وأخيرا يجب ان ننوه إلى أن استخدام البيانات العامة ليس ممكنا دوما سوف نرى الحقا في هذا الكتاب‬ ‫شيفرة مكتوبة ضمن ملفات مختلفة وتنتمي إلى فضاءات أسماء مختلفة تتصل فبما بينها عبر التوابع وفي‬ ‫حاالت كهذه فإن الشيفرة ستجزأ إلى درجة تجعل من المستحيل حفظ البيانات في أماكن عامة من الشيفرة‪.‬‬ ‫يمثل البارامتر ‪ args‬للتابع )( ‪ Main‬طريقة للحصول على المعلومات من خارج التطبيق حيث يتم‬ ‫تحديدها أثناء التنفيذ تمثل هذه المعلومات بارامترات لسطر األوامر وذلك عند تنفيذ التطبيق من خالل‬ ‫سطر األوامر أو محث ‪.‬‬ ‫وبالطبع فإن هذا النوع من التبسيط يمكن أن يقودنا إلى كتابة شيفرة أكثر تعقيدا وأصعب فهما إن تحديد‬ ‫البارامترات بصورة صريحة يسمح لنا برؤية ما يتغير بلمحة سريعة فعندما نرى استدعاء لتابع بالشكل‬ ‫)‪ myFunction (val1 .‬‬ ‫لقد غطينا حتى اآلن معظم التقنيات البسيطة المستخدمة في إنشاء واستخدام المتحوالت سنسلط الضوء في‬ ‫هذا القسم على التابع )( ‪.Main‬‬ ‫لقد قمنا سابقا في هذا الفصل أن التابع )( ‪ Main‬يمثل نقطة دخول لتطبيق ‪ C#‬وأن تنفيذ التطبيق يبدأ‬ ‫بتنفيذ هذا التابع وينتهي بانتهائه لقد رأينا أيضا أن لهذا التابع بارامتر وحيد وهو ‪ string [] args‬إال أننا‬ ‫لم نتعرض إلى هذا البارامتر حتى اآلن سوف نتعلم في هذا القسم فائدة هذا البارامتر وكيف يمكن استخدامه‪.‬‬ ‫لذا وخالصة لذلك إنك حر في استخدام التقنية التي تريحك إال أنه من الواضح في مواضع كثيرة أن‬ ‫استخدام البارامترات والقيم المعادة أفضل بكثير من استخدام البيانات العامة إال أن هناك مواضع خاصة‬ ‫ستحتاج فيها إلى ستحتاج فيها إلى استخدام البيانات العامة وهو أمر ليس بالخطأ إذا أردنا استخدام هذه‬ ‫التقنية‪.‬‬ ‫على كل حال إن هذا النوع من فقدان تعددية االستخدام للتوابع يمكن أن يكون في صالحنا أحيانا فهناك‬ ‫حاالت ال نحتاج فيها إال الستخدام التابع لغرض واحد فقط واستخدام متحوالت البيانات العامة في هذه‬ ‫الحالة سيقلص من احتمال حدوث خطأ ما في استدعاء التابع وريما ينتج من تمرير متحول خاطئ إلى‬ ‫التابع‪.

txt‬في برنامج المفكرة ( ‪ )Notepad‬عند بدء تشغيل البرنامج‬ ‫مباشرة أو سيتم إنشاء هذا الملف إن لم يكن موجودا يمثل النص "‪ "myfile.Console args‬‬ ‫‪ -2‬أضف الشيفرة البرمجية التالية إلى محرر نصوص ‪ C#‬في ‪:class Program‬‬ ‫‪class Program‬‬ ‫{‬ ‫)‪static void Main(string[] args‬‬ ‫{‬ ‫"‪Console .txt‬هنا وسيط في سطر‬ ‫األوامر يمكننا ان نكتب تطبيقات ‪ Console‬بلغة ‪ C#‬تعمل بأسلوب مشابه لهذا السلوك وذلك باستخدام‬ ‫البارامتر ‪.) ‪.‫لقد كان استخدام سطر األوامر السبيل الوحيد لتنفيذ التطبيقات في بيئة ‪ DOS‬أما اليوم فإن بيئة‬ ‫‪ Windows‬الرسومية تغنينا عن ذلك باعتبار أن بإمكاننا تنفيذ التطبيقات والقيام بأعقد األمور بمجرد‬ ‫النقر بزر الفأرة ومع ذلك فلقد أتاح لنا نظام ‪ Windows‬فرصة استخدام محث األوامر‪.Length‬‬ ‫)‪foreach (String arg in args‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪176 -‬‬ ‫‪-‬‬ .WriteLine ("{0} command Line arguments were specified:‬‬ ‫.args‬‬ ‫مالحظة‪:‬‬ ‫يجب أن ننوه إلى أن هناك توقيعان يمكن للتابع )( ‪ Main‬أن يأخذها وهي‪:‬‬ ‫*‬ ‫)(‪static void Main‬‬ ‫*‬ ‫)‪static void Main(string[] args‬‬ ‫أي أنه يمكننا إذا أردنا حذف البارامترات ‪ args‬الذي سنناقشه هنا إن سبب استخدامنا لهذا‬ ‫البارا متر يعود إلى وجوده بصورة تلقائية عند إنشاء تطبيقات ‪ Console‬في ‪Visual‬‬ ‫‪.args .‬‬ ‫لتأخذ برنامج المفكرة ( ‪ )Notepad‬على سبيل المثال يمكننا أن نشغل هذا البرنامج بمجرد كتابة ‪notepad‬‬ ‫في نافذة محث األوامر أو ضمن اإلطار الذي يظهر عند اختيار "تشغيل" (‪ )Run‬من قائمة "ابدأ" (‪)Start‬‬ ‫ويمكننا كتابة أمر كما يلي‪:‬‬ ‫"‪Notepad "myfile.txt‬‬ ‫وفي حالة كهذه سيتم تحميل الملف ‪ myfile.‬‬ ‫تطبيق حول بارامترات سطر االوامر‪:‬‬ ‫‪ -1‬قم بإنشاء تطبيق ‪ Console‬جديد باسم ‪.Studio 2013‬‬ ‫عندما ينفذ تطبيق ‪ Console‬ما سيتم وض ع أية بارامترات في سطر األوامر ضمن المصفوفة ‪ args‬يمكننا‬ ‫ان نستخدم هذه المصفوفة بعد ذلك ضمن تطبيقنا حسب الحاجة الستخراج قيم هذه البارامترات‪.

WriteLine(arg‬‬ ‫.12‬‬ ‫نفذ التطبيق بالضغط على مفتاح ‪ F5‬فيظهر الشكل (‪. ‫.)‪Console.)6-13‬‬ ‫‪-5‬‬ ‫الشكل (‪)6-13‬‬ ‫كيفية العمل‪:‬‬ ‫‪How it Works:‬‬ ‫الشيفرة المستخدمة هنا بسيطة للغاية‪:‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪177 -‬‬ ‫‪-‬‬ .ReadKey‬‬ ‫}‬ ‫}‬ ‫‪ -3‬افتح خصائص المشروع (وذلك بالنقر بزر الماوس األيمن على اسم المشروع ‪Console args‬‬ ‫في إطار مستكشف الحلول ‪ solution Explorer‬ومن ثم اختيار األمر ‪ Properties‬من القائمة‬ ‫المنسدلة)‪.)(‪Console.‬‬ ‫‪ -4‬اختر الصفحة *‪ Debug‬ثم أضف أية وسطاء لسطر األوامر وذلك ضمن الخاصية ‪Command‬‬ ‫‪ Line Arguments‬الشكل (‪.)6-12‬‬ ‫الشكل (‪)6.

‫"‪Console .WriteLine ("{0} command Line arguments were specified:‬‬
‫;) ‪,args .Length‬‬
‫)‪foreach (String arg in args‬‬
‫;)‪Console.WriteLine(arg‬‬
‫;)(‪Console.ReadKey‬‬
‫وهي ال تقوم إال باستخدام البارامتر ‪ args‬كما لو كان كأية مصفوفة بارامترية أخرى في الحقيقة ال تقوم‬
‫الشيفرة بأي شيء سوى طباعة بارامترات سطر األوامر على نافذة الخرج‪.‬‬
‫لقد مررنا بارامترات سطر األوامر في هذا المثال من ضمن نافذة خصائص المشروع في ‪Visual‬‬
‫‪ Studio 2013‬إن تلك تمثل طريقة مفيدة الستخدام بارام ترات سطر األوامر نفسها متى أردنا تنفيذ‬
‫التطبيق من ضمن ‪ Visual Studio 2013‬وذلك بدال من كتابة هذه الوسطاء ضمن محث سطر األوامر‬
‫في كل مرة‪.‬‬

‫لقد تحدثنا عن البنية ‪ Struct‬في الفصل السابق ووجدنا أنها تمثل أسلوبا ممتازا لحفظ عناصر البيانات‬
‫المرتبطة ببعضها في مكان واحد في الحقيقة إن للبنية ‪ struct‬قدرات أكبر من ذلك وأحد هذه القدرات هي‬
‫إمكانية احتوائها على توابع كتضمينها للبيانات إن ذلك يظهر غريبا نوعا ما من الوهلة األولى إال أنه أمر‬
‫مفيد جدا‪.‬‬
‫وكمثال بسيط لنأخذ البنية التالية‪:‬‬
‫‪struct customerName‬‬
‫{‬
‫;‪public string firstName, lastName‬‬
‫}‬

‫إذا كان لدينا متحوالت من النوع ‪ customerName‬فإننا قد نود طباعة االسم الكامل المتضمن على‬
‫‪ firstName‬و‪ lastName‬عندئذ نحن مجبرين على تجميع هذين االسمين مع بعضهما البعض وفي حالة‬
‫كهذه فإننا سنستخدم شيفرة كما يلي‪:‬‬
‫;‪customerName myCustomer‬‬
‫;"‪myCustomer.firstName = "Hussam‬‬
‫;"‪myCustomer.lastName = "ALdeen ALroz‬‬
‫;)‪Console.WriteLine("{0} {1}", myCustomer.firstName, myCustomer.lastName‬‬
‫عند إضافة التوابع إلى البنية ‪ struct‬فإننا سنبسط أمرا كهذا عبر تمركز المهام الشائعة المتعلقة ببيانات‬
‫هذه البنية كتلك ضمن توابع في البنية نفسها يمكننا أن نضع تابعا مناسبا للبنية ‪ customerName‬كما‬
‫يلي‪:‬‬
‫‪struct customerName‬‬
‫{‬
‫;‪public string firstName, lastName‬‬
‫)(‪public string Name‬‬
‫{‬
‫;‪return firstName + " " + lastName‬‬

‫إعداد‪ :‬املهندس حسام الدين الرز‬
‫‪178 -‬‬
‫‪-‬‬

‫}‬
‫}‬

‫إن هذا يظهر مشابها للتوابع التي تناولناها في هذا الفصل فيما عدا أننا لم نستخدم هنا الكلمة ‪static‬‬
‫سيتضح سبب ذلك الحقا خالل هذا الكتاب أما األن يكفي أن تعلم أن هذه الكلمة غير مطلوبة لتوابع ‪struct‬‬
‫يمكننا أن نستخدم هذا التابع كما يلي‪:‬‬
‫;‪customerName myCustomer‬‬
‫;"‪myCustomer.firstName = "Hussam‬‬
‫;"‪myCustomer.lastName = "ALdeen ALroz‬‬
‫;))( ‪Console.WriteLine(myCustomer .Name‬‬
‫;)(‪Console.ReadKey‬‬

‫إن هذه الصيغة أبسط بكثير من السابق وأسهل فهما أيضا‪.‬‬
‫هناك نقطة هامة يجدر اإلشارة إليها هنا وهي أن التابع )( ‪ Name‬يمكن أن يصل مباشرة إلى األعضاء‬
‫‪ firstName‬و‪ lastName‬في البنية ‪ Struct‬أي أن تلك األعضاء عامة ضمن البنية‬
‫‪.customerName‬‬

‫لقد رأينا في هذا الفصل ضرورة مطابقة استدعاء التابع مع توقيعه وذلك كي نتمكن من تنفيذ التابع دون‬
‫أخطاء ويتضمن ذلك حاجتنا لتوابع منفصلة للقيام بعمليات على أنواع مختلفة من المتحوالت لقد حلت لنا‬
‫تقنية التحميل الزائد للعوامل هذه المشكلة وذلك بتوفير إمكانية إنشاء توابع متعددة لها االسم نفسه إال أن‬
‫لكل منها توقيع مختلف‪.‬‬
‫على سبيل المثال لقد استخدمنا الشيفرة التالية مسبقا والتي تتضمن التابع )( ‪:MaxValue‬‬
‫‪class Program‬‬
‫{‬
‫)‪static int MaxValue(int[] intArray‬‬
‫{‬
‫;]‪int maxVal = intArray[0‬‬
‫)‪for (int i = 1; i < intArray.Length; i++‬‬
‫{‬
‫)‪if (intArray[i] > maxVal‬‬
‫;]‪maxVal = intArray[i‬‬
‫}‬
‫;‪return maxVal‬‬
‫}‬
‫)‪static void Main(string[] args‬‬
‫{‬
‫;} ‪int[] myArray = { 10, 84, 35, 99, 21, 8, 0, 48, 11, 1‬‬
‫;)‪int mxVal = MaxValue(myArray‬‬
‫;)‪Console.WriteLine("The maximum value in myArray is {0}", mxVal‬‬
‫;)(‪Console.ReadKey‬‬
‫}‬

‫إعداد‪ :‬املهندس حسام الدين الرز‬
‫‪179 -‬‬
‫‪-‬‬

‫}‬

‫يمكن أن يستخدم التابع )( ‪ MaxValue‬هنا مع المصفوفات ذات النوع ‪ int‬فقط يمكننا أن نعطي هذا‬
‫النوع من التوابع أسماء مختلفة بحسب أنواع البارامترات التي يمكن أن تتقبلها فلربما نسمي التابع‬
‫)( ‪ MaxValue‬باالسم )( ‪ intArrayMaxValue‬ومن ثم نضيف توابع أخرى مثل‬
‫)( ‪ DoubleArrayMaxValue‬وذلك كي نطبق التابع )( ‪ MaxValue‬نفسه على مصفوفة من نوع‬
‫‪ double‬لكن يمكننا كبديل لهذا التعقيد أن نضيف الشيفرة التالية إلى التطبيق السابق‪:‬‬
‫)‪static double MaxValue(double [] intArray‬‬
‫{‬
‫;]‪double maxVal = intArray[0‬‬
‫)‪for (int i = 1; i < intArray.Length; i++‬‬
‫{‬
‫)‪if (intArray[i] > maxVal‬‬
‫;]‪maxVal = intArray[i‬‬
‫}‬
‫;‪return maxVal‬‬
‫}‬

‫االختالف هنا هو أن التابع )( ‪ MaxValue‬أصبح يتقبل مصفوفة تتضمن على قيم من نوع ‪double‬‬
‫وهو نفس اسم التابع الذي يتقبل مصفوفة تتضمن على قيم من نوع ‪ int‬إال أن لهذين التابعين توقيعان‬
‫مختلفان إن هذا أمر مقبول في ‪ C#‬باعتبار أن لكال التابعين توقيع مختلف ولكن ال يمكننا أن نكتب تابعين‬
‫لهما نفس االسم والتوقيع في آن واحد‪.‬‬
‫أصبح لدينا اآلن إصدارتين من التابع )( ‪ MaxValue‬أحدهما يتقبل مصفوفة ‪ int‬ويعيد قيمة من نوع‬
‫‪ int‬واآلخر يتقبل مصفوفة ‪ double‬ويعيد قيمة من نوع ‪ double‬وهي القيمة األكبر في المصفوفة وذلك‬
‫بالنسبة لكال التابعين‪.‬‬
‫إن جمالية هذا النوع من الشيفرة هو أننا لسنا بحاجة لإلشارة صراحة إلى أي من هذين التابعين سنستخدم‬
‫عن د استدعاء التابع باسمه فنحن سنقوم بتمرير بارامتر المصفوفة وسيتم استدعاء التابع المناسب تلقائيا‬
‫باالعتماد على نوع البارامتر الممرر‪.‬‬
‫ويجدر بنا أن ننوه على ميزة أخرى من ملكات الذكاء الموجودة في ‪ Visual Studio 2013‬فإذا كان‬
‫لدينا هذين التابعين وواصلنا كتابة اسم التابع ضمن التابع )( ‪ Main‬سيقوم ‪Visual Studio 2013‬‬
‫بعرض التحميالت الزائدة لهذا التابع تلقائيا فإذا كتبنا الشيفرة التالية مثال‪:‬‬
‫)( ‪double result=MaxValue‬‬

‫سيعطي ‪ Visual Studio 2013‬في هذه الحالة تلميحا ضمن إطار رمادي يستعرض فيه توقيع كال‬
‫التابعين‪.‬‬

‫إعداد‪ :‬املهندس حسام الدين الرز‬
‫‪180 -‬‬
‫‪-‬‬

‫في الحقيقة يمكننا أن نستخدم جميع الجوانب المختلفة لتواقيع التوابع عند التحميل الزائد لها على سبيل‬
‫المثال يمكن ان يكون لدينا تابعين أحدهما يأخذ البارامترات بالقيمة واآلخر يأخذ البارامترات بالمرجع‪:‬‬
‫)‪static void showDouble(ref int val‬‬
‫{‬
‫‪...‬‬
‫}‬

‫)‪static void showDouble(int val‬‬
‫{‬
‫‪...‬‬
‫}‬
‫وفي تلك الحالة فإن تحديد استخدام أي من هذين اإلصدارين مقتصر على شكل االستدعاء أي إن تضمن‬
‫االستدعاء الكلمة ‪ ref‬أوال فاالستدعاء التالي سينفذ التابع ذو بارامتر المرجع‪:‬‬
‫;)‪showDouble(ref val‬‬
‫وأما االستدعاء التالي فسينفذ التابع ذو بارامتر القيمة‪:‬‬
‫;)‪showDouble(val‬‬

‫المفوض (‪ ) delegate‬هو نوع يمكنك من حفظ مراجع للتوابع وعلى الرغم من أن هذا يظهر غريبا نوعا‬ ‫ّ‬
‫للمفوضات إال في فصول‬
‫ّ‬ ‫المفوضات بسيطة للغاية لن تتمكن من فهم الغرض األساسي‬
‫ّ‬ ‫ما إال أن آلية عمل‬
‫الحقة من هذا الكتاب وذلك عندما نتحدث عن األحداث ( ‪ )events‬ومعالجتها إال أنه يمكننا أن نعطي لمحة‬
‫بسيطة عن المفوضات هنا وعندما نستخدمها الحقا ستظهر مألوفة بالنسبة إليك مما يبسط عليك أمورا‬
‫كثيرة‪.‬‬
‫للمفوض جسم كما في التوابع‪.‬‬
‫ّ‬ ‫المفوضات بشكل مشابه للتصريح عن التوابع إال أنه ليس‬ ‫ّ‬ ‫يصرح عن‬
‫المفوض ويمثل التصريح توقيعا لتابع حيث يتألف من قيمة معادة‬ ‫ّ‬ ‫تستخدم الكلمة ‪ delegate‬للتصريح عن‬
‫المفوض يمكننا أن‬
‫ّ‬ ‫المفوض يمكننا أن نصرح عن متحول من نوع هذا‬ ‫ّ‬ ‫والئحة بارامترات وبعد تعريف‬
‫المفوض ومتى قمنا بذلك يمكننا أن نستدعي هذا‬
‫ّ‬ ‫نهيئ هذا المتحول ليمثل مرجعا ألي تابع له نفس توقيع‬
‫التابع باستخدام متحول ‪ delegate‬تماما كما لو أننا نستخدم التابع مباشرة‪.‬‬
‫بما أن لدينا متحول يشير إلى تابع فإن بإمكاننا القيام بأشياء كثيرة بناء على ذلك على سب يل المثال يمكننا‬
‫المفوض‬
‫ّ‬ ‫المفوض ‪ delegate‬إلى تابع على شكل بارامتر حيث سيستخدم التابع هذا‬ ‫ّ‬ ‫أن نمرر متحول‬
‫الستدعاء التابع الذي يشير إليه المتحول‪.‬‬
‫تطبيق حول استخدام المفوّ ض الستدعاء تابع‪:‬‬
‫‪ -1‬قم بإنشاء تطبيق ‪ Console‬جديد باسم ‪.Console delegate‬‬

‫إعداد‪ :‬املهندس حسام الدين الرز‬
‫‪181 -‬‬
‫‪-‬‬

ReadLine (). Console .ToDouble (input .ToDouble (input . if (input =="M") process =new processDelegate (multiply ).WriteLine("Enter 2 numbers separated with a comma:"). double param2) { return param1 * param2. static double multiply(double param1. input=Console .Length -commaPos -1)). Console . double param2=Convert . Console.)6-14( ‫ فيظهر الشكل‬Ctrl+F5 ‫ نفذ التطبيق بالضغط على مفتاح‬-3 )6. double param2) { return param1 / param2.'). else process =new processDelegate (divide ).input . double param2). } static double divide(double param1.WriteLine ("Result:{0}".Substring (0.commaPos)). } static void Main(string[] args) { processDelegate process. double param1=Convert .process (param1 .14( ‫الشكل‬ :‫كيفية العمل‬ How it Works: ‫) حيث يتطابق توقيعه مع توقيعي‬processDelegate ‫تقوم هذه الشيفرة بتعريف مفوض (يحمل االسم‬ :‫ يأخذ هذا المفوض التصريح التالي‬divide () ‫ و‬multiply () ‫التابعين‬ ‫ املهندس حسام الدين الرز‬:‫إعداد‬ 182 - - .WriteLine ("Enter M to multiPly or D to divide:"). int commaPos =input .IndexOf ('. } } . :class Program ‫ في‬C# ‫ أضف الشيفرة البرمجية التالية إلى محرر نصوص‬-2 class Program { delegate double processDelegate(double param1.param2 )).Substring (commaPos +1.ReadLine(). string input = Console.

)"‪Console.commpos-1‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪183 -‬‬ ‫‪-‬‬ . ‫.))‪(commaPos +1.ReadLine‬‬ ‫.)(‪string input = Console.IndexOf ('.Length -commaPos -1‬‬ ‫مالحظة‪:‬‬ ‫الحظ انني لم استخدم هنا أية شيفرة للتحقق من إدخال المستخدم وإذا كانت هذه شيفرة لتطبيق‬ ‫حقيقي فمن الالزم أن نتحقق من جميع احتماالت إدخال المستخدم التي ال تتناسب مع متطلبات‬ ‫التطبيق‪.ToDouble (input .Substring‬‬ ‫.‬‬ ‫.‪processDelegate process‬‬ ‫بعد ذلك هناك شيفرة ‪ C#‬مألوفة من قبل حيث قمنا بطباعة نص على نافذة ‪ Console‬واستخدمنا طريقة‬ ‫جديدة للحصول على البيانات من سلسلة الدخل‪:‬‬ ‫.)'‪int commaPos =input .ToDouble (input .‬‬ ‫توضيح‪:‬‬ ‫لقد استخدمنا هنا أمرين جديدين من أوامر معالجة السالسل النصية لم نتحدث عنهما في الفصل السابق‬ ‫لقد طلبنا من المستخدم إدخال قيمتين رقميتين بحيث يفصل بينهما برز الفاصلة "‪ " .‬لقد قلنا أن ما‬ ‫نحصل عليه من المستخدم ال يمثل إال سلسلة نصية (قيمة من نوع ‪)String‬حتى لو ظهر لنا غير ذلك‬ ‫كأن يقوم المستخدم بإدخال قيمة رقمي ة فقط نحتاج هنا لفصل القيمتين عن بعضهما و التعامل معهما‬ ‫كال على حدى استخدمنا هنا األمر )(‪ IndexOf‬والذي يتقبل قيمة من نوع ‪ Char‬كبارامتر له ويعيد‬ ‫قيمة رقمية من نوع ‪ int‬تمثل أول موقع للرمز ‪ Char‬في السلسلة النصية لقد احتفظنا بهذا الموقع‬ ‫ضمن المتحول ‪ commaPos‬حت ى اآلن لم نقم بفصل القيمتين عن بعضهما البعض والخطوة التالية‬ ‫هي استخدام األمر )( ‪ Substring‬والذي يعطينا سلسلة نصية ويتقبل بارامترين يمثل األول موقع‬ ‫الرمز الذي يمثل بداية السلسلة الجزئية ويمثل الثاني طول هذه السلسلة الجزئية وبالتالي فإن القيمة‬ ‫األولى التي أد خلها المستخدم تبدأ من أول رمز في السلسلة النصية ذو الدليل ‪ 0‬وصوال إلى موقع‬ ‫الفاصلة أي أن طول السلسلة الجزئية هو نفسه دليل الفاصلة وأما القيمة الثانية فهي تبدأ من بعد‬ ‫الفاصلة أي عند الدليل ‪ commpos+1‬ووصوال إلى نهاية السلسلة أي بطول ‪input.WriteLine("Enter 2 numbers separated with a comma:‬‬ ‫.Substring (0.))‪double param1=Convert .commaPos‬‬ ‫‪double param2=Convert .input .Length-‬‬ ‫‪.param2‬‬ ‫تبدأ الشيفرة الموجودة في التابع )(‪ Main‬بالتصريح عن متحول للمفوض السابق‪:‬‬ ‫)‪static void Main(string[] args‬‬ ‫{‬ ‫. double param2‬‬ ‫تحدد الكلمة ‪ delegate‬أن هذا التعريف لمفوض وليس لتابع (الحظ أن شكل التعريف مشابه جدا لتعريف‬ ‫التابع) بعد ذلك هناك توقيع المفوض والذي يتضمن على قيمة معادة من نوع ‪ double‬وعلى بارامترين‬ ‫من نوع ‪ double‬ويمكنك أن تسمي المفوضات وبارامتراتها بأي اسم تريد لقد سمينا المفوض هنا باالسم‬ ‫‪ processDelegate‬والبارامترين باالسم ‪ param1‬و‪.)‪delegate double processDelegate(double param1.

3‬‬ ‫}‬ ‫هذا يعني أن بإمكاننا التحكم بسلوك التوابع بتمرير هذه التوابع على شكل مفوضات على سبيل المثال يمكن‬ ‫أن يكون لدينا تابع يقوم بترتيب مصفوفة من نوع ‪ string‬أبجديا هناك العديد من الطرق لترتيب اللوائح‬ ‫والتي يختلف أداؤها بحسب صفات الالئحة المراد ترتيبها وباستخدام المفوضات يمكننا تحديد الطريقة‬ ‫المستخدمة وذلك بتمرير مفوض تابع خوارزمية ترتيب محددة إلى تابع الترتيب‪.)) ‪Console .)recursion‬‬ ‫لنأخذ على سبيل المثال الشيفرة التالية‪:‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪184 -‬‬ ‫‪-‬‬ .param2‬‬ ‫ليس هذا و حسب بل ويمكننا أن نقوم بعمليات إضافية على هذا المتحول كتمريره إلى تابع على شكل‬ ‫بارامتر كمثال على ذلك‪:‬‬ ‫)‪static void executeFunction (processDelegate process‬‬ ‫{‬ ‫.)"‪Console .2.)( ‪input=Console .‬‬ ‫هناك الكثير من االستخدامات للمفوضات إال أنها تستخدم بصورة خاصة لمعالجة األحداث وهذا ما سنراه‬ ‫في المستقبل‪.) ‪process =new processDelegate (divide‬‬ ‫لقد استخدمنا هنا أسلوبا غريبا نوعا ما إلسناد مرجع لتابع إلى متحول المفوض ‪ process‬وكما في إسناد‬ ‫قيم المصفوفة فإن علينا استخدام الكلمة ‪ new‬إلنشاء مفوض جديد وبعد هذه الكلمة سنحدد نوع المفوض‬ ‫وتزويده ببارامترات يشير إلى التابع الذي نود استخدامه الحظ أن هذا البارامتر ال يتطابق مع توقيع‬ ‫المفوض وإنما يمثل اسم التابع الذي سيمثله المتحول‪.) ‪process =new processDelegate (multiply‬‬ ‫‪else‬‬ ‫.)‪process(2.process (param1 .‬‬ ‫وأخيرا يمكننا أن نستدعي التابع باستخدام مفوضه حيث يمكننا أن نستخدم متحول المفوض تماما كما لو‬ ‫أننا استخدمنا التابع نفسه‪:‬‬ ‫.WriteLine ("Enter M to multiPly or D to divide:‬‬ ‫.‬‬ ‫هنا يمكننا أن نستدعي التابع ضمن جسم التابع نفسه؟! الجواب ليس هذا وحسب بل إن ذلك يعد أحد تقنيات‬ ‫البرمجة المتقدمة وفي مراحل متقدمة من البرمجة قد تستخدمها يمكن أن نسمي ذلك باالستدعاء الذاتي‬ ‫للتوابع ما يطلق على هذا األسلوب البرمجي بالتعاودية (‪.ReadLine‬‬ ‫وباالعتماد على دخل المستخدم سيتم تهيئة م تحول المفوض ‪:process‬‬ ‫)"‪if (input =="M‬‬ ‫.‫بعد ذلك سنطلب من المستخدم أن يحدد ما إذا كان يود طباعة حاصل ضرب القيمتين أم حاصل قسمة‬ ‫األول على الثاني‪:‬‬ ‫. 3.WriteLine ("Result:{0}".

.)‪return val * factorial(val ..‪int x‬‬ ‫.1‬‬ ‫}‬ ‫في الحقيقة يمثل هذا التابع خوارزمية احتساب العاملي فلنفرض مثال أننا استدعينا هذا التابع كما يلي‪:‬‬ ‫)‪static void Main(string[] args‬‬ ‫{‬ ‫. ‫)‪static int factorial(int val‬‬ ‫{‬ ‫)‪if (val <= 0‬‬ ‫.WriteLine("5!={0}".)‪x = factorial(5‬‬ ‫.‪return 1‬‬ ‫‪else‬‬ ‫.)(‪Console.ReadKey‬‬ ‫}‬ ‫لنرى ما سيحدث ضمن التابع سيأخذ البارامتر ‪ val‬القيمة ‪ 5‬وبما أن هذه القيمة ال تحقق الشرط ‪val<=0‬‬ ‫فسوف ينفذ السطر‪:‬‬ ‫.‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪185 -‬‬ ‫‪-‬‬ .)‪Console. x‬‬ ‫.1‬‬ ‫}‬ ‫فإن ذلك سيؤدي إلى حدوث خطأ في التنفيذ نتيجة الستمرارية االستدعاء التعاودي دون توقف مما سيؤدي‬ ‫إلى إنهاك مكدس النظام وتوقف البرنامج عن العمل‪.)‪return val * factorial(val .‬‬ ‫إن االستدعاء التعاودي موضوع برمجي متقدم ولقد أحببت ان انوه عنه هنا في حديثنا عن التوابع لكن إذا‬ ‫أردت ان تقرأ في موضوع كهذا يمكنك البحث عن كتب تتحدث عن الخوارزميات البرمجية‪.*1‬‬ ‫‪=5*4*3*2*1‬‬ ‫‪=120‬‬ ‫في الحقيقة أن هناك عدة أمور يجب مراعاتها عند است خدام االستدعاء التعاودي وأهم هذه األمور هي أن‬ ‫يكون هناك مخرج من التعاودية دائما ولهذا السبب وجد الشرط‪:‬‬ ‫)‪if (val <= 0‬‬ ‫في الشيفرة السابقة فإذا كتبنا التابع السابق بالشكل‪:‬‬ ‫)‪static int factorial(int val‬‬ ‫{‬ ‫.)‪return val * factorial(val ..1‬‬ ‫أي سيتم استدعاء التابع )(‪ factorial‬من ضمن التابع نفسه هذه المرة ببارامتر مختلف عن السابق‬ ‫)‪ factorial(5-1‬وبالتالي سيأخذ البارامتر ‪ val‬في االستدعاء الثاني القيمة ‪ 4‬وبما أن ‪ 4‬ليست أصغر أو‬ ‫تساوي ‪ 9‬فسيعود التابع الستدعاء نفسه مجددا لكن هذه المرة وفقا لالستدعاء التالي‪:‬‬ ‫)‪ factorial(4-1‬وتستمر عجلة االستدعاء بهذه الصورة إلى أن تصل قيمة ‪ val‬للصفر عندها سيتوقف‬ ‫التابع والمحصلة هي إعادة النتيجة‪:‬‬ ‫‪=Val*(Val-1)*(Val-2).

Console‬‬ ‫‪‬‬ ‫تبادل البيانات مع التوابع بواسطة القيم المعادة والبارامترات‪.‬‬ ‫‪‬‬ ‫المفوضات‪.Struct‬‬ ‫‪‬‬ ‫التحميل الزائد للتوابع‪.‬‬ ‫‪‬‬ ‫التابع )( ‪ Main‬وكيفية استخدام بارامترات سطر األوامر‪.‬‬ ‫‪‬‬ ‫المصفوفات البارامترية‪. ‫الخالصة‪:‬‬ ‫‪Summary:‬‬ ‫لقد أخذنا في هذا الفصل لمحة كاملة حول كيفية استخدام التوابع في لغة ‪ C#‬ولقد تعرفنا على الكثير من‬ ‫المزايا اإلضافية المتعلقة بالتوابع مثل المفوضات واالستدعاء التعاودي لكن للحديث بقية عن التوابع وإليك‬ ‫ملخصا عما تناولناه في هذا الفصل‪:‬‬ ‫تعريف واستخدام التوابع في تطبيقات ‪.‬‬ ‫‪‬‬ ‫مفهوم مدى المتحوالت‪.‬‬ ‫‪‬‬ ‫استخدام بارامترات الخرج إلعادة قيم إضافية‪.‬‬ ‫‪‬‬ ‫االستدعاء التعاودي‪.‬‬ ‫‪‬‬ ‫استخدام التوابع ضمن بنية ‪.‬‬ ‫‪‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪186 -‬‬ ‫‪-‬‬ .‬‬ ‫‪‬‬ ‫تمرير البارامترات بالمرجع أو القيمة‪.

‬‬ ‫وباإلضافة إلى هذا فإننا سنتناول تقنيات معالجة األخطاء المتوفرة في ‪ C#‬إن هذا سيمكننا من اتخاذ‬ ‫التدابير الوقائية في حاالت يحتمل وقوع األخطاء فيها وكتابة شيفرة برمجية مرنة بالصورة الكافية بحيث‬ ‫تمكننا من االلتفاف حول األخطاء التي تمثل أن تكون أخطاء فادحة تتسبب في إيقاف التطبيق بصورة غير‬ ‫محببة إن التقنيات تمثل جزءا من لغة ‪ C#‬وليست بميزة في ‪ Visual Studio 2013‬إال أن ‪Visual‬‬ ‫‪ Studio 2013‬يوفر بعض األدوات ا لتي تساعدنا في االستفادة من هذه التقنية أيضا‪.‬‬ ‫في حاالت كهذه ستجد أن إمكانيات تنقيح األخطاء في ‪ Visual Studio 2013‬تقدم لك مساعدة أكثر من‬ ‫رائعة وفي ال جزء األول من هذا الفصل سنلقي نظرة على بعض التقنيات التي يقدمها لنا ‪Visual Studio‬‬ ‫‪ 2013‬لحل بعض المشاكل الشائعة‪.C#‬‬ ‫األخطاء في الشيفرة هو شيء يحتمل إلى حد كبير أن تقع فيه أثناء البرمجة ومهما كنت مبرمجا جيدا فإنك‬ ‫على األغلب سترتكب أخطاء برمجية وبالطبع فإن هناك أخطاء ال تؤثر على سير البرنامج كخطأ إمالئي‬ ‫في كتابة اسم زر ما وهناك أخطاء تتسبب في توقف التطبيق عن العمل تماما تعرف هذه األخطاء باألخطاء‬ ‫الفادحة ‪ fatal errors‬تصنف األخطاء الفادحة إلى أخطاء بسيطة ناتجة عن خطأ في كتابة صيغة ما‬ ‫‪ syntax errors‬وهناك أخطاء منطقية ‪ logic errors‬وتحدث عندما يخفق تطبيقنا في القيام بمهمة ما‬ ‫كالقسمة على صفر مثال‪. ‫الفصل السابع‬ ‫معاجلة األخطاء‬ ‫لقد تناولنا في الفصول السابقة من الكتاب معظم أساسيات البرمجة بلغة ‪ C#‬وقبل أن ننتقل إلى الحديث‬ ‫عن البرمجة كائنية التوجه في الجزء التالي من الكتاب فإن الوقت قد حان للحديث عن تنقيح ومعالجة‬ ‫األخطاء في شيفرة ‪.‬‬ ‫في الحقيقة يمكن أن تصبح عملية معالجة األخطاء كابوسا حقيقيا للمبرمج خصوصا إذا تذمر المستخدم‬ ‫من شيء يعمل بصورة غير منطقية في التطبيق في هذه الحالة عليك أن تبحث عن الخطأ خالل الشيفرة‬ ‫في محاولة الكتشاف ما يحدث وكيف يجب أن تعدل شيفرتك لكي تتجاوز هذا الخطأ‪.‬‬ ‫إن هذا النوع من األخطاء هو االسهل وفي ‪ Visual Studio 2013‬يتم اكتشاف هذه األخطاء فورا مثال‬ ‫على هذا الخطأ كتابة الجملة التالية‪:‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪187 -‬‬ ‫‪-‬‬ .

‪byte x = 2015446‬‬ ‫طبعا تعرف ان حدود النوع ‪ byte‬أصغر من هذا الحد ولكن في اإلصدارات القديمة لم يكن هذا ليظهر‬ ‫خطا حيث أن الجملة مكتوبة نحويا بشكل سليم كما ترى‪.‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪188 -‬‬ ‫‪-‬‬ .))(‪firstNumber = Convert.‬‬ ‫وتقسم األخطاء المنطقية إلى ثالثة أنواع أساسية وهي‪:‬‬ ‫‪:User Error -1‬‬ ‫أخطاء تنتج من استخدام البرنامج لو افترضنا المثال السابق لـ ‪ byte‬نقوم فيه بتخزين عمر المستخدم‬ ‫لكن المستخدم قام بإدخال رقم ‪ 10000‬هذا الخطأ من المستخدم سيتسبب في المشاكل لك فيما لو لم‬ ‫تكن قد اضفت شرط التأكد من عدم تجاوز العمر لحد معين‪ ،‬ايضا ً ادخال بيانات نصية في خانة العمر‬ ‫وخالفه تندرج تحت اسم أخطاء المستخدم‪..‬‬ ‫‪:Exceptions -2‬‬ ‫وهو النوع األشهر من األخطاء مثل محاولة فتح ملف او قاعدة بيانات غير موجودة مثالً حيث لم يتم‬ ‫تحميلها بصورة صحيحة أو محاولة قراءة بيانات من قاعدة البيانات في حين انها تساوي ‪ null‬بدون‬ ‫استخدام ‪ nullable type‬أو محاولة الكتابة إلى ملف نصي ‪ Readonly‬وخالفه من األخطاء‬ ‫المشهورة‪.ToDuble(Console.‬‬ ‫هذا النوع من األخطاء هو األصعب‪ ،‬فعلى صعيد كتابة الكود ربما ال يوجد خطأ نحوي ولكنه خطأ منطقي‬ ‫يظهر عند التنفيذ‪ ،‬ابسط مثال على هذا الخطأ هو كتابة كود كالتالي‪:‬‬ ‫.‬الخ‪،‬‬ ‫هذه األخطاء قد ال تظهر لـ ‪ % 99‬من المستخدمين ولكنا تظهر لمستخدم واحد فقط‪ ،‬لذا في العادة‬ ‫تكون هناك عدة نسخ تجريبية من اي برنامج لمحاولة معرفة أماكن امثال هذه األخطاء وتعديلها قبل‬ ‫طرح النسخة الرسمية‪.‬‬ ‫‪: Bugs -3‬‬ ‫أكثر األخطاء شهرة ال يمكن حصرها وال عدها‪ ،‬وتوجد في جميع البرامج بما فيهم نسخة الويندوز التي‬ ‫تستخدمها في العادة لن يخلو برنامج منها ولكننا نحاول تفاديها قدر المستطاع‪ ،‬قد تحدث بسبب نسيان‬ ‫حذف متغير او قراءة متغير من قيمة موجودة اصالً في الذاكرة ونحن نظن انها قيمة فارغة ‪ ..ReadLine‬‬ ‫بالطبع ستجد رسالة خطأ قبل التنفيذ تخبرك بأن الخاصية ‪ ToDuble‬غير موجودة مثل هذه األخطاء هي‬ ‫االسهل ويتم اكتشافها من خالل بيئة لغة البرمجة التي تعمل عليها وفي ‪ Visual Studio 2013‬أصبحت‬ ‫رسائل الخطأ واضحة للغاية ويمكن تفسيرها بسهولة وحلها‪. ‫.

‬‬ ‫سوف نلقي نظرة على هذه التقنيات في هذا الفصل وسنبين كيفية استخدامها وذلك كي نتمكن من تنقيح‬ ‫وتصحيح األخطاء التي قد نرتكبها عند كتابة تطبيقاتنا‪.VS‬‬ ‫‪ ‬قراءة قيم المتحوالت وتحريرها أثناء تنفيذ التطبيق‪.‬‬ ‫‪ ‬تعديل محتوى المتحوالت أثناء تنفيذ التطبيق‪.WriteLine‬‬ ‫والذي يقوم بطباعة نص ما على نافذة ‪ Console‬يمكننا أن نستفيد من هذا األمر عندما نقوم بتطوير‬ ‫التطبيقات وذلك لمساعدتنا في تتبع ما يحدث أثناء تنفيذ الشيفرة على سبيل المثال‪:‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪189 -‬‬ ‫‪-‬‬ .‬‬ ‫سوف نقسم هذه التقنيات إلى قسمين وذلك وفقا الستخداماتها وبصورة عامة تنقيح الشيفرة يتم إما بمقاطعة‬ ‫تنفيذ التطبيق أو إنشاء مالحظات لتحليل المشاكل الحقا وبالنسبة لـ ‪ VS‬فإن تنقيح الشيفرة يتم إما أثناء‬ ‫تنفيذ الشيفرة (نمط عدم المقاطعة) أو في نمط مقاطعة التطبيق (‪ )Break mode‬أي عند إيقاف التنفيذ‬ ‫العادي للشيفرة مؤقتا سوف نناقش تقنيات التنقيح باستخدام نمط عدم التوقف أوال‪.‬‬ ‫‪ ‬تنفيذ شيفرة التطبيق سطرا بسطر‪.‬‬ ‫‪ ‬اإليقاف المؤقت لتنفيذ التطبيق أو إعادة تنفيذه من جديد‪.‬‬ ‫‪ ‬مراقبة المتغيرات التي تطرأ على قيم المتحوالت خالل تنفيذ التطبيق‪.‫عندما نقوم بتنفيذ برامجنا في نمط التنقيح ‪ debug mode‬فإن هناك أمور كثيرة تحدث خلف الكواليس‬ ‫وليس مجرد تنفيذ ل لشيفرة التي كتبناها وحسب‪ .‬‬ ‫‪ ‬إجراء استدعاءات تجريبية للتوابع‪.‬يقوم المنقح ‪ debugger‬ببناء معلومات رمزية‬ ‫‪ symbolic information‬عن تطبيقك وبهذه المعلومات فإن ‪ VS‬سيصبح قادرا على معرفة ما يحدث‬ ‫عند تنفيذ كل سطر برمجي في الشيفرة إن ما نقصده بالمعلومات الرمزية هي معلومات متعلقة بأسماء‬ ‫المتحوالت المست خدمة في الشيفرة قبل ترجمتها حيث يتم مطابقتها مع القيم الموجودة ضمن شيفرة التطبيق‬ ‫المترجمة أثناء التنفيذ فهذه الشيفرة المترجمة غير مفهومة من قبل اإلنسان كالشيفرة التي نكتب بها تطبيقاتنا‬ ‫يتم االحتفاظ بهذه المعلومات ضمن ملفات لها االمتداد ‪ pdb‬وهو ما ستجده في مجلد ‪ Debug‬ضمن مجلد‬ ‫المشروع إن ذلك يمكننا من القيام بالعديد من العمليات تتضمن‪:‬‬ ‫‪ ‬طباعة معلومات التنقيح إلى ‪.‬‬ ‫إن أحد أكثر األوامر التي مرت معنا منذ بداية هذا الكتاب إلى اآلن هو األمر )(‪Console.‬‬ ‫‪ ‬إنهاء تنفيذ التطبيق تلقائيا عند الوصول إلى نقاط معينة من الشيفرة‪.

Output‬‬ ‫لقد نوهنا على إطار ‪ Output‬في الفصول السابقة وهو موجود في الجزء السفلي من بيئة تطوير ‪VS‬‬ ‫ويشاركه بنفس الموضع إطار ‪ Task List‬لقد تعرفنا على هذا اإلطار أيضا ورأينا أنه يعرض معلومات‬ ‫متعلقة باألخطاء والمهام الموجودة في الشيفرة ويتضمن ذلك األخطاء التي تحصل أثناء كتابة الشيفرة‬ ‫يمكننا ان نستخدم هذه النافذة أيضا لعرض معلومات تفحصيه من عندنا وذلك بكتابتها مباشرة ضمن‬ ‫اإلطار يمكننا أن نرى هذا اإلطار كما في الشكل (‪:)7-1‬‬ ‫الشكل (‪)7-1‬‬ ‫مالحظة‪:‬‬ ‫الحظ أن لإلطار ‪ Output‬ثالثة أنماط يمكننا تحديد أحدهما من خال ل تحديد اسم النمط في‬ ‫مربع القائمة المنسدلة يمكننا أن ننتقل بين أنماط بناء التطبيق ‪ Build‬وتنقيحه ‪Debug‬‬ ‫وتنفيذه بصورة اختبارية ‪ Test Run‬يعطينا نمطي ‪ Build‬و‪ Debug‬معلومات متعلقة بزمن‬ ‫تنفيذ التطبيق وباألخطاء الحاصلة عندما سأشير إلى الكتابة إلى إطار ‪ Output‬في هذا القسم‬ ‫فإنني أعني الكتابة في نمط عرض ‪ Debug‬إلطار ‪.‬‬ ‫.)"‪MyFunc("Do something‬‬ ‫.WriteLine("MyFunc() Function execute completed.Output‬‬ ‫إن ما يقوم به ‪ VS‬من كتابة معلومات متعلقة بتطبيقنا الذي يجري تنفيذه حاليا في إطار ‪ Output‬لهو أمر‬ ‫مشابه لملف التسجيل ‪ logging file‬الذي تقوم بإنشائه لتسجيل ما يحدث أثناء تنفيذ تطبيقاتك إال أننا هنا‬ ‫لسنا بحاجة لالهتمام بكيفية الوصول إلى الملف والكتابة ضمنه‪.)"‪Console.‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪190 -‬‬ ‫‪-‬‬ .)"‪Console.‬‬ ‫تستعرض هذه الشيفرة كيف يمكننا الحصول على معلومات إضافية متعلقة بالتابع )(‪ MyFunc‬إن القيام‬ ‫بذلك جيد جدا لكن سيظهر خرج ‪ Console‬غير منظم فليال وكطريقة بديلة لذلك فإن بإمكاننا ان نخرج‬ ‫النصوص إلى مكان منفصل وهو إطار الخرج في ‪ VS‬المسمى بإطار ‪. ‫.WriteLine("MyFunc() Function about to be called.

Output‬‬ ‫هناك أمران يمكننا استخدامهما لذلك‪:‬‬ ‫األمر )(‪.‬‬ ‫إن الخرج العام لهذين األمرين هو كما يلي‪:‬‬ ‫>‪<category>:<message‬‬ ‫على سبيل المثال لنف ترض اننا كتبنا في موضوع ما من شيفرة التابع ‪ MyFunc‬السطر التالي‪:‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪191 -‬‬ ‫‪-‬‬ .WritLine‬فاألمر‬ ‫)(‪ Console.WriteLine‬باالستدعاء المطلوب لكتابة النص في المكان الذي نريد ضمن إطار ‪.Trace.Debug.WriteLine‬‬ ‫األمر )(‪.WriteLine‬‬ ‫إن هذين األمرين متشابهان لدرجة كبيرة جدا إال هناك اختالف واحد بينهما وهو أن األمر األول يعمل‬ ‫فقط عند بناء التطبيق في مرحلة التنقيح ‪ debug build‬أما األمر الثاني فهو يعمل عند بناء التطبيق في‬ ‫مرحلة اإلطالق ‪ release build‬في الحق يقة سيقوم المترجم بتخطي جميع أوامر‬ ‫)(‪ Debug.WriteLine‬عند بناء التطبيق في مرحلة اإلطالق فهذا األمر سيختفي من شيفرة اإلطالق‪.‬‬ ‫توضيح‪:‬‬ ‫يمكن أن تكون لدينا إصدارتين من الشيفرة البرمجية ناتجة من ملف مصدري وحيد‪ :‬إصدارة‬ ‫التنقيح ‪ debug version‬وإصدارة اإلطالق ‪ release version‬تستعرض إصدارة التنقيح‬ ‫جميع المعلومات التفحصية اإلضافية التي نحتاج إليها في مرحلة تنقيح التطبيق أما إصدارة‬ ‫اإلطالق فهي ال تقوم بذلك ولن تعرض رسائل على المستخدمين يمكن أن تزعجهم وذلك‬ ‫باعتبار ان هذه الرسائل مفيدة جدا لنا أثناء تطوير تطبيق وليس للمستخدم النهائي‪.WritLine‬يستخدم الصيغة }‪ {x‬لربط النصوص مع قيم المتحوالت بينما يجب أن نستخدم‬ ‫العامل ‪ +‬للقيام بهذا النوع من الربط عند استخدام األمرين السابقين وذلك ألن هذين األمرين ال يتقبالن‬ ‫ذلك أي أن هذين األمرين يتقبالن بارامترا واحدا يمثل السلسلة النصية التي نود طباعتها في إطار ‪Output‬‬ ‫ويمكن أن ي تقبال بارامترا ثانيا حيث يستخدم لعرض تصنيف النص المطبوع إن ذلك يمكننا من معرفة أية‬ ‫رسائل يتم طباعتها في إطار ‪ Output‬في حال كانت هناك رسائل متشابهة في أماكن مختلفة من التطبيق‪.‬‬ ‫الحظ أن هذين األمرين ال يعمالن بنفس الصورة التي يعمل بها األمر )(‪ Console.‫إن كتابة النصوص في إطار ‪ Output‬بسيط للغاية فنحن ببساطة سنستبدل استدعاءات األمر‬ ‫)(‪ Console.

Generic. Debug. ‫ املهندس حسام الدين الرز‬:‫إعداد‬ 192 - - . for (int i = 1. using System. count = 1.Tasks. namespace Console_Output { class Program { static int Maxima(int[] integers. if (integers[i] > maxVal) { maxVal = integers[i]. Debug. oldIndices.Threading. :‫ سيكون كما يلي‬Output ‫عندئذ فإن الخرج في إطار‬ MyFunc: Added 1 to i ‫في الحقيقة إننا لن نستخدم أمري التنقيح لطباعة نصوص وحسب وإنما سنستخدمها في الغالب لطباعة‬ ."). indices = new int[1]. i < integers. int maxVal = integers[0].Text. Debug.‫قيمة متحول ما‬ :Output ‫تطبيق حول طباعة نص في إطار‬ .at element index 0.CopyTo(indices.Linq. indices[count .WriteLine("Added 1 to i”.Length. 0). indices = new int[1].WriteLine("Maximum value initialized to" + maxVal + ".Collections. int[] oldIndices = indices. int count = 1.").").1] = i. i++) { Debug. using System. using System.New value is" + maxVal + ". indices = new int[count].WriteLine("Maximum value search started. out int[] indices) { Debug.at element index" + i + ". indices[0] = i. using System.Console Output ‫ جديد باسم‬Console ‫ قم بإنشاء تطبيق‬-1 :class Program ‫ في‬C# ‫ أضف الشيفرة البرمجية التالية إلى محرر نصوص‬-2 using System.WriteLine("New maximum found. using System.").WriteLine("Now looking at element at index" + i + ". “MyFunc”). } else { if (integers[i] == maxVal) { count++.Diagnostics. indices[0] = 0.

exe' (CLR v4.0__b77a5c561934e089\mscorli ‫ املهندس حسام الدين الرز‬:‫إعداد‬ 193 - - . } static void Main(string[] args) { int[] testArray = { 4.").0. 2.0. 9. 1. 4. int maxVal = Maxima(testArray.Net\assembly\GAC_32\mscorlib\v4. 3. Console. maxVal).vshost.WriteLine(index). 7. } } } } F5 ‫ أو بالضغط على الزر‬Start‫ نفذ التطبيق في نمط التنقيح باختيار األمر‬-3 :‫مالحظة‬ Solution ‫الحظ أنه يمكنك تحديد نمط تنفيذ الشيفرة من خالل مربع القائمة المنسدلة‬ .exe): Loaded 'C:\Windows\Microsoft. Debug. foreach (int index in maxValIndices) { Console. out maxValIndices).WriteLine("Duplicate maximum found at element" + "index" + i + ". Debug.WriteLine("Maximum value" + maxVal + "found with" + count + "occurrences. } } } Trace. return maxVal.)7-2( ‫ فيظهر الشكل‬Ctrl+ F5 ‫ أو بالضغط على مفتاح‬Debugging )7-2( ‫الشكل‬ ‫ يمكنك اختيار نمط التنقيح من‬Debug ‫ في نمط التنقيح‬Output ‫ انظر اآلن إلى محتويات إطار‬-4 ‫خالل مربع القائمة المنسدلة في أعلى النافذة حيث ال تتضمن هذه القائمة سوى ثالثة خيارات‬ :‫ سيظهر الخرج كما يلي‬Debug‫ و‬Build Order‫ و‬Build 'Console Output. int[] maxValIndices.0.").WriteLine("Maximum value {0} found at element" + "indices:".0_4. 9 }.vshost. 3.WriteLine("Maximum value search completed."). 8. 7. 7.30319: Console Output.‫ الموجود في شريط األدوات‬Configurations Start without ‫ وستختفي ب سرعة ولو أننا نفذنا الشيفرة بدون تنقيح‬Console ‫ستظهر نافذة‬ .

Skipped loading symbols.0. Skipped loading symbols.Xml.vshost.exe): Loaded 'C:\Windows\assembly\GAC_MSIL\Microsoft.vshost.vshost.exe'.vshost.0.Linq\v4.vshost.30319: Console Output. 'Console Output. Skipped loading symbols.Utilities.vshost.Net\assembly\GAC_MSIL\Microsoft.vshost. Symbols loaded. Module is optimized and the debugger option 'Just My Code' is enabled.CSharp\v4.0_4.0 .0. Module is optimized and the debugger option 'Just My Code' is enabled.dll'. Module is optimized and the debugger option 'Just My Code' is enabled.exe): Loaded 'C:\Windows\Microsoft.Debugger. Skipped loading symbols.0.0.Drawing.0.exe): Loaded 'D:\‫كتاب‬ ‫\شارب سي‬c#‫ المشاريع\اف دي بي الكتاب‬c#\Console Output\Console Output\bin\Debug\Console Output.exe' (CLR v4.Windows. 'Console Output.exe): Loaded 'C:\Windows\assembly\GAC_MSIL\Microsoft.Forms\v4. Skipped loading symbols.30319: Console Output.0.Sync.Core.0.0__b77a5c561934e089\System.30319: Console Output. Skipped loading symbols.dll'.vshost. Module is optimized and the debugger option 'Just My Code' is enabled.0_4.exe' (CLR v4. 'Console Output.30319: Console Output.30319: Console Output.VisualStudio. 'Console Output.0_4.0.exe' (CLR v4.exe): Loaded 'C:\Windows\Microsoft. Skipped loading symbols.0.vshost.Net\assembly\GAC_MSIL\System.dll'.Forms.30319: Console Output.Net\assembly\GAC_MSIL\System.0_4.VisualStudio.Runtime.vshost. 'Console Output. Module is optimized and the debugger option 'Just My Code' is enabled. The thread 0xa40 has exited with code 259 (0x103).Data\v4.0.Core\v4.vshost.vshost.exe' (CLR v4.0.Debugger. Skipped loading symbols.HostingProcess.exe' (CLR v4. dll'.Xml.0.0__b77a5c561934e08 9\System.Net\assembly\GAC_32\System. Module is optimized and the debugger option 'Just My Code' is enabled.Utilities\12. 'Console Output. Module is optimized and the debugger option 'Just My Code' is enabled. ‫ املهندس حسام الدين الرز‬:‫إعداد‬ 194 - - .0.0.0__b77a5c561934e089\Syst em.0.0. 'Console Output.30319: Console Output.Runtime\12.Linq. Module is optimized and the debugger option 'Just My Code' is enabled. The thread 0x12bc has exited with code 259 (0x103).exe): Loaded 'C:\Windows\Microsoft.vshost.exe' (CLR v4.Net\assembly\GAC_MSIL\System.dll'.30319: Console Output.exe): Lo aded 'C:\Windows\Microsoft.0__b77a5c561934e089\Sys tem.dll'.0__b77a5c5619 34e089\System. Skipped loading symbols.Net\assembly\GAC_MSIL\System\v4.vshost.exe'.CSharp.0__b03f5f7f11d50a 3a\Microsoft.0.VisualStudio.0__b77a5c561934e089\Sy stem.0.vshost.exe' (CLR v4.0.Utilities.VisualStudio.0. Module is optimized and the debugger option 'Just My Code' is enabled.dll'.exe): Loaded 'C:\Windows\assembly\GAC_MSIL\Microsoft. Skipped loading symbols.exe): Loaded 'D:\‫كتاب‬ ‫\شارب سي‬c#‫ المشاريع\اف دي بي الكتاب‬c#\Console Output\Console Output\bin\Debug\Console Output.0__b 77a5c561934e089\System.vshost.vshost. Module is optimized and the debugger option 'Just My Code' is enabled.dll'.0.0. Module is optimized and the debugger option 'Just My Code' is enabled.exe): Loaded 'C:\Windows\Microsoft. The thread 0x688 has exited with code 259 (0x103).Drawing\v4.0_4. Module is optimized and the debugger option 'Just My Code' is enabled.Net\assembly\GAC_MSIL\System.dll'.0.0.exe): Loaded 'C:\Windows\Microsoft. Skipped loading symbols.exe' (CLR v4.Utilities.Data.Data.exe' (CLR v4.0_4.0__b03f5f7f11d50a3a \System.0.HostingProcess.dll'.vshost.30319: Console Output.0__b 03f5f7f11d50a3a\Microsoft.DataSetExtensions\v4. 'Console Output. Skipped loading symbols.dll'.exe' (CLR v4.30319: Console Output.HostingProcess.0__b03f5f7f1 1d50a3a\Microsoft. 'Console Output. 'Console Output.vshost.0_4.VisualStudio.vshost.0_4.0__b03f5f7f11d50a3a\Microsoft.30319: Console Output.exe' (CLR v4.vshost.dll'.vshost.0. Skipped loading symbols.0.0.exe' (CLR v4.0.vshost.Data.Net\assembly\GAC_MSIL\System.vshost. 'Console Output.Windows.0.dll'.0.0.0.Xml\v4. 'Console Output. 'Console Output.b.vshost.DataSetExtensions.HostingProcess. 'Console Output.0.Xml.Net\assembly\GAC_MSIL\System.0_4.30319: Console Output.30319: Console Output.vshost.exe' (CLR v4.VisualStudio. Module is optimized and the debugger option 'Just My Code' is enabled.vshost.0.0.Sync \12.vshost.exe' (CLR v4.vshost. Module is optimized and the debugger option 'Just My Code' is enabled.exe): Loaded 'C:\Windows\Microsoft.exe): Loaded 'C:\Windows\Microsoft.exe): Loaded 'C:\Windows\Microsoft.30319: Console Ou tput. Skipped loading symbols.

Maximum value9found with2occurrences. Skipped loading symbols.exe: Program Trace' has exited with code 0 (0x0).Configuration\v4. Duplicate maximum found at elementindex6. Duplicate maximum found at elementindex4.'Console Output.vshost. Now looking at element at index1.New value is7.at element index9.vshost. Now looking at element at index6. Now looking at element at index4.Configuration ‫ من العمود‬Release ‫ تأكد من اختيار‬ .Configuration. Module is optimized and the debugger option 'Just My Code' is enabled. Now looking at element at index10.vshost.at element index1. Now looking at element at index2. Duplicate maximum found at elementindex11.at element index 0. Maximum value search completed. New maximum found.0. Now looking at element at index8.0__b03f5f7f11 d50a3a\System.exe' (CLR v4.vshost.Active Solution Configurations ‫ من مربع القائمة المنسدلة‬Release ‫ واآلن اختر‬ ‫ املهندس حسام الدين الرز‬:‫إعداد‬ 195 - - . Maximum value search started. New maximum found. Now looking at element at index5.Net\assembly\GAC_MSIL\System. The program '[1712] Console Output. Now looking at element at index7.exe' has exited with code 0 (0x0). Now looking at element at index11.exe): Loaded 'C:\Windows\Microsoft.0. Maximum value initialized to4. New maximum found.30319: Console Output. Now looking at element at index3. The program '[1712] Console Output. The thread 0x1250 has exited with code 259 (0x103). :‫ وذلك باتباع الخطوات التالية‬release ‫ واآلن انتقل إلى نمط االطالق‬-5 ‫ ستظهر نافذة كما في‬Build ‫ من القائمة‬Configuration Manager ‫ اختر األمر‬ :)7-3(‫الشكل‬ )7-3( ‫الشكل‬ .at element index7.0.0_4. Now looking at element at index9.dll'. The thread 0x424 has exited with code 259 (0x103).New value is8.New value is9.

‫ نفذ التطبيق مرة أخرى لكن هذه المرة سيحدث التنفيذ في نمط اإلطالق ثم ألق نظرة على إطار‬-6 :‫ عند انتهاء التنفيذ‬Output 'Console Output.Net\assembly\GAC_MSIL\System. Skipped loading symbols.0.0. Skipped loading symbols.vshost.0. Module is optimized and the debugger option 'Just My Code' is enabled.exe): Loaded 'C:\Windows\Microsoft. Module is optimized and the debugger option 'Just My Code' is enabled.exe' (CLR v4. Module is optimized and the debugger option 'Just My Code' is enabled.0__b77a5c561934e089\Sy stem.vshost.exe): Loaded 'C:\Windows\Microsoft.30319: Console Output.vshost.30319: Console Output.exe): Loaded 'C:\Windows\Microsoft.Drawing.0.Net\assembly\GAC_MSIL\Microsoft.dll'.CSharp\v4.0_4.0.0_4.Net\assembly\GAC_MSIL\System. Skipped loading symbols.dll'. Module is optimized and the debugger option 'Just My Code' is enabled.0.30319: Console Output.exe): Loaded 'C:\Windows\Microsoft.dll'.vshost.vshost. Module is optimized and the debugger option 'Just My Code' is enabled.30319: Console Output.30319: Console Output.vshost. Skipped loading symbols.exe'.30319: Console Output.vshost.exe): Loaded 'C:\Windows\Microsoft. 'Console Output.30319: Console Output.dll'.Linq.Xml.0__b77a5c561934e089\Sys tem.0__b77a5c561934e089\System.exe): Loaded 'C:\Windows\Microsoft.0__b77a5c561934e089\Syst em.0__b03f5f7f11d50a3a\Microsoft.vshost. Skipped loading symbols.0.0. dll'.0.Sync \12.Windows.vshost. Module is optimized and the debugger option 'Just My Code' is enabled.0__b03f5f7f11d50a 3a\Microsoft.vshost.HostingProcess. 'Console Output.0.vshost.exe' (CLR v4.0 .Linq\v4.vshost.0.exe): Loaded 'C:\Windows\assembly\GAC_MSIL\Microsoft.Xml\v4.0_4.Runtime.DataSetExtensions. Module is optimized and the debugger option 'Just My Code' is enabled.exe): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_32\System. The thread 0x37c has exited with code 259 (0x103).0.vshost. 'Console Output. 'Console Output. 'Console Output.0_4.VisualStudio.Data.vshost.0__b77a5c5619 34e089\System.dll'.exe' (CLR v4. Module is optimized and the debugger option 'Just My Code' is enabled.0.exe): Loaded 'C:\Windows\Microsoft.Windows.vshost. Skipped loading symbols.0. Module is optimized and the debugger option 'Just My Code' is enabled.Data.Debugger.vshost.30319: Console Output.exe' (CLR v4.0__b77a5c561934e08 9\System.0_4.0__b 03f5f7f11d50a3a\Microsoft.vshost.0.dll'.vshost. Skipped loading symbols. Skipped loading symbols.0__b03f5f7f11d50a3a \System.Data\v4.exe' (CLR v4.Net\assembly\GAC_MSIL\System.0.Xml.exe' (CLR v4. 'Console Output.exe' (CLR v4.VisualStudio.0_4.0. 'Console Output.vshost.exe): Loaded 'C:\Windows\Microsoft. 'Console Output.exe): Loaded 'D:\‫كتاب‬ ‫\شارب سي‬c#‫ المشاريع\اف دي بي الكتاب‬c#\Console Output\Console Output\bin\Release\Console Output.0.VisualStudio.0__b 77a5c561934e089\System.0.exe' (CLR v4. 'Console Output.exe' (CLR v4.30319: Console Output.0_4. Module is optimized and the debugger option 'Just My Code' is enabled.Net\assembly\GAC_32\mscorlib\v4.Xml.Utilities.exe' (CLR v4.0_4.0.0.vshost. Skipped loading symbols.exe): Loaded 'C:\Windows\Microsoft.Data. Module is optimized and the debugger option 'Just My Code' is enabled.Utilities. Module is optimized and the debugger option 'Just My Code' is enabled.Net\assembly\GAC_MSIL\System.VisualStudio.30319: Console Output.vshost.Net\assembly\GAC_MSIL\System\v4.vshost.vshost.dll'.Forms.exe' (CLR v4.30319: Console Output.Utilities \12.HostingProcess. Skipped loading symbols.0. Skipped loading symbols.dll'.vshost.VisualStudio.CSharp.VisualStudio.0__b03f5f7f1 1d50a3a\Microsoft.0. 'Console Output. Skipped loading symbols.0.dll'.Net\assembly\GAC_MSIL\System. ‫ املهندس حسام الدين الرز‬:‫إعداد‬ 196 - - .exe): Loaded 'C:\Windows\assembly\GAC_MSIL\Microsoft.30319: Console Output.0.30319: Console Output.DataSetExtensions\v4. 'Console Output.Core.dll'.Utilities.0_4.vshost. Module is optimized and the debugger option 'Just My Code' is enabled.Drawing\v4.0.vshost.dll'.dll'.0.exe): Loaded 'C:\Windows\assembly\GAC_MSIL\Microsoft.0.vshost.0.HostingProcess.vshost.0. Skipped loading symbols.Net\assembly\GAC_MSIL\System.0.Core\v4.HostingProcess.vshost.0.0.Debugger.30319: Console Output.0. Module is optimized and the debugger option 'Just My Code' is enabled.0.0.0__b77a5c561934e089\mscorli b.exe' (CLR v4.0.Forms\v4.exe' (CLR v4. 'Console Output. 'Console Output.0_4. Skipped loading symbols.0.0.Runtime\12.exe' (CLR v4.Sync.

exe): Loaded 'D:‬‬ ‫‪ c#\Console Output\Console Output\bin\Release\Console‬المشاريع\اف دي بي الكتاب‪\c#‬شارب سي‬ ‫‪Output.‫‪The thread 0x1274 has exited with code 259 (0x103).exe' (CLR v4.‬‬ ‫‪'Console Output.NET 2013‬‬ ‫بالحل أو ‪ Solution‬حيث يمكن أن يتضمن الحل عدة مشاريع‪.WriteLine("Maximum value search started.30319: Console Output.Debug.vshost.‬‬ ‫‪The thread 0x738 has exited with code 259 (0x103).Diagnostics‬‬ ‫إن ذلك يب سط الوصول إلى األوامر التي تحدثنا عنها قبل البدء بهذا المثال وذلك ألنها موجودة ضمن‬ ‫فضاء األسماء ‪ System.‪using System.Configuration.Diagnostics‬فعند استخدام تعليمة ‪ using‬هذه فإنه يمكننا كتابة أوامر التنقيح‬ ‫كما يلي‪:‬‬ ‫.0.exe' (CLR v4.0_4.Diagnostics.Solution Configuration‬‬ ‫إن ذلك ألن مشروعنا أو تطبيقنا يمثل جزءا من مشروع أكبر يسميه ‪Visual Studio. Symbols loaded.exe'.‬‬ ‫‪Maximum value9found with2occurrences.Net\assembly\GAC_MSIL\System.0.‬‬ ‫وبدون هذه التعليمة فإن علينا تحديد االسم التام لألمر أو التابع كما يلي‪:‬‬ ‫.vshost.0.‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪197 -‬‬ ‫‪-‬‬ .‬‬ ‫كيفية العمل‪:‬‬ ‫‪How it Works:‬‬ ‫إن هذا التطبيق هو عبارة عن مثال موسع للتطبيق الذي تناولناه في الفصل السابق فهو يقوم باستخدام تابع‬ ‫الحتساب القيمة العظمى في مصفوفة عددية إال أن هذا التابع يع يد مصفوفة تتضمن األدلة التي يحتلها‬ ‫العنصر األكبر في المصفوفة وبالتالي يمكن للشيفرة التي استدعت التابع أن تعالج هذه العناصر‪.0__b03f5f7f11‬‬ ‫‪d50a3a\System.vshost.30319: Console Output.dll'.‬‬ ‫‪The program '[4132] Console Output. Skipped loading symbols.exe' has exited with code 0 (0x0).‬‬ ‫توضيح‪:‬‬ ‫لقد اضطررنا هنا إلى تحديد نمط اإلطالق ‪ Release‬في موضعين ضمن ‪ VS‬لقد استخدمنا‬ ‫في هذا المثال نافذة ‪ Configuration Manager‬لتحديد نمط بناء المشروع واستخدمنا‬ ‫شريط األدوات لتحديد نمط بناء الحل (‪ )Solution‬ككل ويمكننا تحديد نمط الحل من خالل‬ ‫نافذة ‪ Configuration Manager‬أيضا وذلك ضمن مربع القائمة المنسدلة ‪Active‬‬ ‫‪.‬‬ ‫‪The program '[4132] Console Output.)"‪Debug.exe): Loaded‬‬ ‫‪'C:\Windows\Microsoft. Module is optimized and the‬‬ ‫‪debugger option 'Just My Code' is enabled.)"‪System.vshost.vshost.Configuration\v4.WriteLine("Maximum value search started.‬‬ ‫‪The thread 0x12c0 has exited with code 259 (0x103).0.‬‬ ‫لتناول الشيفرة السابقة بتفصيل أكبر كبداية الحظ أننا استخدمنا تعليمة ‪ using‬جديدة كجزء من الشيفرة‪:‬‬ ‫.‬‬ ‫كتاب\‪'Console Output.exe: Program Trace' has exited with code 0‬‬ ‫‪(0x0).vshost.

CopyTo(indices.‪count++‬‬ ‫.1] = i‬‬ ‫‪Debug. 0‬‬ ‫.‪int[] oldIndices = indices‬‬ ‫.‬‬ ‫ولربما يجدر بنا أن ننوه إلى أن المنهج الذي استخدمناه في انشاء مصفوفة األدلة فبدال من إنشاء مصفوفة‬ ‫حجمها مساو لحجم المصفوفة األصلية فإننا قمنا بإنشاء مصفوفة حجمها مطابق تماما لعدد المواقع التي‬ ‫وجد فيها العنصر األكبر في المصفوفة الحظ انه ال يمكننا تغيير حجم المصفوفة متى تم إنشائها ولكننا‬ ‫هنا قمنا بإعادة إنشاء المصفوفة في كل مرة نحصل فيها على موقع جديد للعنصر األكبر‪.)"‪"index" + i + ".‬‬ ‫تقوم الشيفرة الموجودة ضمن التابع )(‪ Main‬بتهيئة مصفوفة اختبارية بقيم من نوع ‪ int‬وتسمى هذه‬ ‫المصفوفة باالسم )(‪ testArray‬يقوم هذا التابع أيضا بالتصريح عن مصفوفة من نوع ‪ int‬أخرى تسمى‬ ‫‪ maxValIndices‬لحفظ دليل العنصر األكبر في مصفوفة ضمنها حيث سيتم طباعة هذه األدلة والقيمة‬ ‫العظمى على نافذة ‪.]‪indices = new int[count‬‬ ‫.Console‬‬ ‫أما التابع )(‪ Maxima‬فه و معقد قليال إال أنه يستخدم معظم الصيغ التي تعرفنا عليها في الفصول السابقة‬ ‫إن خوارزمية البحث المستخدمة في هذا التابع مشابهة لتلك المستخدمة في التابع )(‪ MaxVal‬الذي تعرفنا‬ ‫عليه في الفصل السابق فيما عدا أن التابع )(‪ Maxima‬يقوم هنا بحفظ مواقع وجود القيمة العليا في‬ ‫المصفوفة‪.‪indices[count .‬‬ ‫}‬ ‫الحظ أننا نحتفظ بالمصفوفة ‪ indices‬القديمة ضمن مصفوفة جديدة باسم ‪ oldIndices‬المحلية الحظ‬ ‫أيضا أنه سيتم نسخ القيم في المصفوفة ‪ oldIndices‬إلى المصفوفة ‪ indices‬الجديدة وذلك باستخدام‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪198 -‬‬ ‫‪-‬‬ .‬‬ ‫تبدأ عملية البحث بافتراض أن العنصر األول من المصفوفة األصلية (تسمى هذه المصفوفة ضمن التابع‬ ‫باالسم ‪ )integers‬هو العنصر ذو القيمة األكبر من المصفوفة وهو موجود في مكان واحد فقط من‬ ‫المصفوفة وهو الدليل ‪ 9‬مبدئيا سنقوم بحفظ القيم العظمى التي وجدناها ضمن متحول باسم ‪ count‬وهو‬ ‫ما سيمكننا من تتبع المصفوفة ‪.indices‬‬ ‫إن الجسم الرئيسي للتابع متمثل بحلقة ‪ for‬والتي تقوم بالمرور خالل جميع العناصر في المصفوفة‬ ‫‪ integers‬بدءا من العنصر الثاني ذو الدليل رقم ‪ 1‬سيتم مقارنة كل قيمة في المصفوفة مع قيمة المتحول‬ ‫‪ maxVal‬والذي يمثل القيمة األكبر اآلنية في المصفوفة فإذا كانت قيمة ‪ maxVal‬عندئذ سيأخذ المتحول‬ ‫‪ maxVal‬قيمة ذلك العنصر وسيتم تعديل المصفوفة ‪ indices‬تتضمن دل يل هذا العنصر أيضا ولكن إن‬ ‫كانت قيمة العنصر مساوية لقيمة ‪ maxVal‬فذا يعني أننا حصلنا على موقع آخر للعنصر األكبر في‬ ‫المصفوفة وبالتالي سيتم إضافة موقع هذا العنصر كقيمة في المصفوفة ‪ indices‬إن هذه المصفوفة الجديدة‬ ‫هي اكبر بعنصر واحد من المصفوفة ‪ indices‬القديمة‪.‬‬ ‫أن الشيفرة التي تقوم بهذه العملية هي كما يلي‪:‬‬ ‫)‪if (integers[i] == maxVal‬‬ ‫{‬ ‫.WriteLine("Duplicate maximum found at element" +‬‬ ‫.)‪oldIndices. ‫إن استخدام تعليمة ‪ using‬يبسط من شيفرتنا البرمجية ويقلص من حجمها‪.

WriteIf‬‬ ‫تستخدم هذه التوابع البارامترات نفسها وإليك صيغة أحد هذه التوابع وليكن )(‪:Debug.WriteLine‬والمحصلة النهائية لهذين األمرين عند تنفيذ التطبيق‬ ‫في نمط ‪ Debug‬هو سجل كامل للخطوات التي تمت ضمن الحلقة اما في نمط ‪ Release‬فإننا رأينا فقط‬ ‫نتيجة العملية برمتها وذلك ألنه لن ينفذ أي أمر )(‪ Debug.Debug.Trace.Trace.‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪199 -‬‬ ‫‪-‬‬ .WriteLine‬في هذا النمط‪.Write‬‬ ‫ويستخدم هذان التابعان نفس صيغة التابع )(‪ WriteLine‬أي بارامتر أو بارامترين يتضمن األول الرسالة‬ ‫أو النص المراد إظهارها و الثاني صنف الرسالة إال أنهما ال يؤديان لالنتقال إلى سطر جديد أي أن الكتابة‬ ‫تتم في نفس السطر‪.CopyTO‬يقوم هذا التابع بنسخ جميع القيم الموجودة في المصفوفة >‪<array‬‬ ‫ولصقها في مصفوفة أخرى جديدة من نفس نوع المصفوفة >‪.WriteLineIf‬‬ ‫‪ ‬التابع )( ‪.<category‬‬ ‫الحظ أن صيغة هذا التابع مشابهة لصيغة التابع )( ‪ .Trace.WriteLineIf‬‬ ‫.Write‬‬ ‫‪ ‬التابع )(‪.‬‬ ‫على سبيل المثال يمكننا أن نستخدم األمر )(‪ Debug.WriteLineIf(<condition>.Debug.‫التابع )(‪ <array>.WriteLineIf‬لطباعة نص على إطار ‪Output‬‬ ‫عند حدوث حالة معينة وبالتالي يمكننا أن نستخدم هذا األمر في أشياء كثيرة ضمن الشيفرة وذلك باالعتماد‬ ‫على الشرط فإن لم يتحقق الشرط لن يظهر شيء على إطار ‪ Output‬وإن تحقق فسيظهر النص الموافق‬ ‫لألمر المحدد في البارامتر‪.‬‬ ‫هناك أوامر أخرى أيضا مثل‪:‬‬ ‫‪ ‬التابع )(‪.‬‬ ‫لقد الحظنا هنا وجود تابعي )(‪ Write‬خالل هذا المثال وهما مشابهان للتابع )(‪ Console.WriteLine‬و)(‪ Trace. Debug.<array‬‬ ‫هناك العديد من النصوص التي تم طباعتها خالل هذه الشيفرة وذلك باستخدام األمرين‬ ‫)(‪ Debug.<textToOutputIfTrue>.Write‬من‬ ‫الناحية الوظيفية‪:‬‬ ‫‪ ‬التابع )(‪.WriteLine‬فيما عدا أن هناك بارامترا‬ ‫إضافيا هو ويمثل هذا البارامتر شرطا منطقيا أي يعيد قيمة من نوع ‪ bool‬فإن كانت نتيجة الشرط ‪true‬‬ ‫فسيتم عندئذ طباعة النص في البارامتر والصنف في إطار ‪ Output‬أما إذا لم يتحقق الشرط فلن يتم‬ ‫طباعة أي شيء‪.)>‪Debug.WriteLineIf‬‬ ‫‪ ‬التابع )(‪.WriteIf‬‬ ‫‪ ‬التابع )( ‪.Debug.

4‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪200 -‬‬ ‫‪-‬‬ .‬‬ ‫الطريقة األبسط للدخول في نمط م قاطعة التنفيذ للتطبيق هي بالنقر على زر التوقف ‪ Break All‬أثناء‬ ‫تنفيذ التطبيق يمكنك أن تجد هذا الزر ضمن شريط أدوات ‪ Debug‬إن شريط األدوات هذا ال يظهر‬ ‫بصورة افتراضية ويجب أن تظهره بنفسك وللقيام بذلك انقر بزر الفارة األيمن على منطقة اشرطة األدوات‬ ‫ثم اختر من القائمة المنسدلة البند ‪ Debug‬كما في الشكل (‪. ‫توضيح‪:‬‬ ‫الحظ أن أوامر ‪ Debug‬و ‪ Trace‬جميعها ليس لها أي تأثير على نسخة التطبيق النهائية‬ ‫فعند إنهاء التطبيق وتوزيعه فإن هذه األوامر لن تقدم أو تؤخر من شيء في نسخة التطبيق‬ ‫الموزعة وإنما هي لألغراض البرمجية فقط‪.)7-4‬‬ ‫الشكل (‪)7.‬‬ ‫تعمل تقنيات التنقيح المتبقية في نمط المقاطعة ويمكن الدخول في هذا النمط بواسطة عدة طرق وجميعها‬ ‫تؤدي إلى توقف البرنامج عن التنفيذ بشكل مؤقت إن أول ما سنتعلمه في هذا الفصل هو كيفية الدخول في‬ ‫نمط المقاطعة ومن ثم سنتحدث عما يمكننا تحقيقه في نمط المقاطعة‪.

‬‬ ‫إعادة تشغيل التطبيق‪.‬‬ ‫وعند تنفيذ التطبيق سيتغير مظهر شريط األدوات هذا إلى الشكل (‪:)7-6‬‬ ‫الشكل (‪)7.‬‬ ‫ربما يعد اإليقاف المؤقت للتطبيق من أبسط الطرق للدخول في نمط المقاطعة إال أن ذلك ال يعطينا تحكما‬ ‫بالموضع الذي نود التوقف عنده تماما يسمح لنا هذا النوع من التوقف بمقاطعة التطبيق أثناء طلبه إدخاال‬ ‫من المستخدم مثال ولكن في العديد من الحاالت قد نحتاج إلى التوقف خالل معالجة طويلة أو خالل حلقة‬ ‫مثال وهذا ال يمكن تحقيقه باستخدام اإليقاف المؤقت بشكل مباشر‪.‬‬ ‫وبصورة عامة فإنه من األفضل في حالة كتلك أن نستخدم نقاط المقاطعة‪. ‫سيظهر عندئذ شريط أدوات ‪ Debug‬وهو كما في الشكل (‪:)7-5‬‬ ‫الشكل (‪)7.‬‬ ‫تمثل نقاط المقاطعة عالمات في شيفرتك المصدرية تتم مقاطعة تنفيذ التطبيق عند الوصول إليها يمكننا‬ ‫إعداد نقاط المقاطعة وفقا لما يلي‪:‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪201 -‬‬ ‫‪-‬‬ .‬‬ ‫إيقاف التطبيق كليا (إن هذا ال يؤدي إلى الدخول في نمط المقاطعة وإنما إلى إنهاء تنفيذ التطبيق‬ ‫تماما)‪.5‬‬ ‫تمكنن ا األزرار األربعة األولى من اليسار بالتحكم اليدوي بمقاطعة التطبيق ونالحظ في الشكل أن هناك‬ ‫ثالث ازرار مظللة بلون رمادي هذا يعني أنه ال يمكننا استخدامها في الوقت الحالي وذلك ألن التطبيق‬ ‫غير منفذ حاليا أما الزر الممكن هنا فهو ‪ Start‬والذي يقوم بتنفيذ التطبيق تماما كما لو أننا ضغطنا على‬ ‫المفتاح ‪ F5‬أو اخترنا األمر ‪ Run‬من القائمة ‪ Debug‬أما بقية األزرار فسوف نتحدث عنها عندما نحتاج‬ ‫إلى استخدامها‪.6‬‬ ‫واآلن فإن األزرار الثالثة التي كانت مظللة مسبقا أصبحت ممكنة وهي تسمح لنا بالقيام بما يلي‪:‬‬ ‫إيقاف التطبيق مؤقتا والدخول في نمط المقاطعة‪.

‬‬ ‫‪ ‬الدخول في نمط المقاطعة عند الوصول إلى نقطة المقاطعة وقد تغيرت قيمة متحول ما منذ آخر‬ ‫مرة تم فيها الوصول إلى نقطة المقاطعة نفسها‪. ‫‪ ‬الدخول في نمط المقاطعة فورا عند الوصول إلى نقطة المقاطعة‪.‬‬ ‫مالحظة‪:‬‬ ‫تذكر أن نقاط المقاطعة متوفرة فقط أثناء بناء التطبيق في نمط التنقيح ‪ Debug‬أي أنه لن يتم‬ ‫االستجابة إلى نقاط المقاطعة عند ترجمة التطبيق في نمط اإلطالق حيث سيتم تجاهل جميع نقاط‬ ‫المقاطعة وكأنها غير موجودة‪.7‬‬ ‫ستظهر نقطة المقاطعة كدائرة حمراء بجانب السطر الذي ستحدث عنده وسيتم تظليل ذلك السطر باللون‬ ‫األرجواني كما في الشكل (‪:)7-8‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪202 -‬‬ ‫‪-‬‬ .‬‬ ‫‪ ‬الدخول في نمط المقاطعة عند الوصول إلى نقطة المقاطعة إذا أخذ تعبير منطقي القيمة ‪.‬‬ ‫هناك عدة طرق إلضافة نقاط المقاطعة فإلضافة نقطة مقاطعة بسيطة تقوم بمقاطعة تنفيذ التطبيق مباشرة‬ ‫عند الوصول إليها سنقوم بالنقر بزر الفأرة األيسر على الشريط الرمادي الموجود إلى يسار إطار محرر‬ ‫الشيفرة أو بالنقر بزر الفأرة األيمن على السطر البرمجي ثم اختيار األمر‪ Insert Breakpoint‬كما في‬ ‫الشكل (‪:)7-7‬‬ ‫الشكل (‪)7.True‬‬ ‫‪ ‬الدخول في نمط المقاطعة عند الوصول إلى نقطة المقاطعة لعدد محدد من المرات‪.

8‬‬ ‫يمكننا تتبع نقاط المقاطعة الموجودة في الملف وذلك باستخدام إطار نقاط المقاطعة ‪ Breakpoints‬لكن‬ ‫علينا ان نعرض هذا اإلطار أوال وذلك باختيار األمر ‪ Breakpoints‬من القائمة الفرعية ‪Windows‬‬ ‫من القائمة ‪ Debug‬سيظهر عندئذ إطار مشابه للشكل (‪ )7-9‬وسيتوضع في نفس موضع إطار ‪Task‬‬ ‫‪ List‬وإطار ‪:Output‬‬ ‫الشكل (‪)7. ‫الشكل (‪)7.‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪203 -‬‬ ‫‪-‬‬ .9‬‬ ‫يمكننا باستخدام هذا اإلطار حجب نقاط مقاطعة محددة وذلك بإزالة اإلشارة الموجودة إلى يسار وصف‬ ‫نقطة المقاطعة حيث ستظهر نقطة المقاطعة المحجوبة على شكل دائرة حمراء مفرغة ويمكننا حذف نقاط‬ ‫المقاطعة أو تحرير خصائصها‪.‬‬ ‫نالحظ في إطار ‪ Breakpoints‬الخاصتين ‪ Condition‬و‪ Hit Count‬وهما الخاصيتان المتوفرتان إال‬ ‫أنهما مفيدتان جدا يمكننا تحرير هاتين الخاصيتين بالنقر بزر الفارة األيمن على نقطة المقاطعة ضمن‬ ‫الشيفرة او من خالل هذا اإلطار ومن ثم اختيار األمر ‪ Properties‬من القائمة المنسدلة يمكننا عندئذ‬ ‫استخدام ثالثة بنود ‪ Function‬و‪ File‬و ‪ Address‬وذلك لتغيير موضع نقطة المقاطعة يسمح لنا البند‬ ‫‪ Address‬بتحديد عنوان مطلق في الذاكرة لنقطة المقاطعة وهناك الزران ‪ Condition‬و‪Hit Count‬‬ ‫المستخدمتان لتغيير هاتين الخاصيتين االتي نوهنا عنهما‪.

19‬‬ ‫يستخدم هذا اإلطار لكتابة تعبير منطقي يستخدم كشرط لمقاطعة التنفيذ عند نقطة المقاطعة تلك حيث يمكنك‬ ‫تضمن التعبير أية متحوالت ضمن مدى نقطة المقاطعة‪.‬‬ ‫ّ‬ ‫هنا كتابة هذا التعبير ويمكنك أن‬ ‫وعند اختيار الزر ‪ Hit Count‬سيظهر اإلطار كما في الشكل (‪:)7-11‬‬ ‫الشكل (‪)7.12‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪204 -‬‬ ‫‪-‬‬ . ‫وباختيارك لزر ‪ Condition‬سيظهر إطار كما في الشكل(‪:)7-19‬‬ ‫الشكل (‪)7.11‬‬ ‫يمكننا هنا أن نحدد عدد المرات التي سينفذ عنده سطر نقطة المقاطعة قبل أن تقدح الشكل (‪ )7-12‬يبين‬ ‫الخيارات التي يوفرها مربع القائمة المنسدلة في هذا اإلطار‪:‬‬ ‫الشكل (‪)7.

‫إن الخيار الذي سيتم تحديده في مربع القائمة هنا مرتبط بقيمة مربع النص المجاور والذي سيحدد ضمنه‬ ‫قيمة موافقة لهذا الخيار‪.‬‬ ‫إن ميزة المقاطعة تلك مفيدة جدا خصوصا في الحلقات الطويلة فيمكننا مثال أن نقاطع تنفيذ حلقة ما بعد الـ‬ ‫‪ 5999‬دورة األولى‪.Debug‬‬ ‫يأخذ هذان ال تابعان ثالثة بارامترات فقط يمثل األول قيمة منطقية فإن كانت القيمة ‪ false‬سيتم قدح التوكيد‬ ‫أما البارامتر الثاني والثالث فهما يمثالن بارامترين نصيين حيث ستكتب هذه النصوص ضمن رسالة‬ ‫التوكيد وضمن إطار ‪ Output‬أيضا إليك مثاال يبين كيفية استخدام التابع ‪:Debug.‬‬ ‫والتوكيدات ‪ assertions‬ع بارة عن تعليمات يمكن ان تقاطع تنفيذ التطبيق برسالة ما وتستخدم التوكيدات‬ ‫عادة اثناء تطوير التطبيق وذلك للتأكد من ان األمور تسير على ما يرام على سبيل المثال يمكننا في نقطة‬ ‫ما من التطبيق أن نحتاج ألن تكون قيمة متحول ما اقل من ‪ 19‬يمكننا ان نستخدم توكيدا لتفحص ما إذا‬ ‫كان ذلك قد حدث فعال ام ال وإن لم يحدث ذلك سيتم مقاطعة التطبيق وعند حدوث التوكيد فإننا امام ثالثة‬ ‫خيارات إما إلغاء التوكيد ‪ Abort‬مما سيؤدي إلى إنهاء التطبيق أو إعادة المحاولة ‪ Retry‬مما سيتسبب‬ ‫في الدخول في نمط المقاطعة او التجاهل ‪ Ignore‬حيث سيكمل تنفيذ التطبيق بصورة طبيعية‪.‬‬ ‫.Trace.Assert‬‬ ‫وكما هو الحال مع توابع التنقيح فإن هذين التابعين سيترجمان فقط أثناء بناء التطبيق في نمط التنقيح‬ ‫‪.‬‬ ‫إن التوكيدات مفيدة في أغلب األحيان عند المراحل األولى الختيار التطبيق يمكننا أن نوزع تطبيقنا في‬ ‫نمط اإلطالق بحيث يتضمن التابع )(‪ Trace.Assert‬‬ ‫‪ ‬التابع )(‪.Debug.‬‬ ‫هناك طريقتان إضافيتان للدخول في نمط المقاطعة األولى تقتضي بمقاطعة التطبيق عند رمي اعتراض‬ ‫في معالج ‪ unhandled exception‬وسوف نغطي موضوع االعتراضات الحقا في هذا الفصل عند‬ ‫الحديث عن معالجة األخطاء واما الطريقة األخرى فهي مقاطعة التنفيذ عند طرق توليد توكيد ‪assertion‬‬ ‫ما‪.‬‬ ‫وكما رأينا ان هناك توابع تستخدم للتنقيح ‪ Debug‬فإن هناك تابعان للتوكيد‪:‬‬ ‫‪ ‬التابع )(‪.Assert‬حيث يمكن للمستخدمين أن يكونوا على دراية بما‬ ‫يحصل في التطبيق وبالتالي يستطيعون أن ينقلوا هذه المعلومات إلى المطورين عندئذ سيتمكن المطورون‬ ‫من حل المشكلة حتى لو لم يعرفوا كيف سارت األمور بصورة خاطئة‪.)"‪"Assertion occurred in Main().Assert‬‬ ‫‪Debug.‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪205 -‬‬ ‫‪-‬‬ ."maxval is 10 or greater.".Assert(maxVal<10 .

ebp‬‬ ‫‪0000019c pop ebp‬‬ ‫‪0000019d ret 4‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪206 -‬‬ ‫‪-‬‬ .". "Variable out of bounds.‬‬ ‫حيث ستظهر الرسالة التالية على المستخدم كما في الشكل (‪:)7-13‬‬ ‫الشكل (‪)7.‬‬ ‫.13‬‬ ‫فإن كانت بيئة تطوير ‪ Visual Studio.NET 2013‬مثبتة على جهاز المستخدم وضغط على زر‬ ‫‪ Retry‬ضمن نسخة من التطبيق تعمل في نمط اإلطالق ‪ Release‬عندئذ لن يعرض على المستخدم‬ ‫شيفرتنا البرمجية وإنما ستعرض أمامهم تعليمات بلغة التجميع ‪ assembly language‬تمثل شيفرة‬ ‫تطبيقنا إليك مثاال لبعض التعليمات التي قد تراها بالنسبة للشيفرة السابقة‪:‬‬ ‫‪00000196 nop‬‬ ‫‪00000197 pop ebx‬‬ ‫‪00000198 pop esi‬‬ ‫‪00000199 pop edi‬‬ ‫‪0000019a mov esp .Assert(maxVal < 5.) "‪"Please contact vendor with the error code KCW001.‫يمكننا على سبيل المثال توفير معلومات موجزة عن الخطأ في السلسلة النصية األولى وبتعليمات عما‬ ‫يجب القيام به في السلسلة النصية الثانية‪:‬‬ ‫‪Trace.

‬‬ ‫‪ o‬البند ‪ :Locals‬يستعرض جميع المتحوالت الموجودة في المدى‪.‬‬ ‫ستركز األقسام التالية على ما يمكننا القيام به عند مقاطعة تنفيذ التطبيق وبصورة عامة فإننا لن ندخل في‬ ‫نمط المقاطعة إال عندما نود أن نتتبع األخطاء في الشيفرة أو فقط لنتأكد من أن األمور تسير على ما يرام‬ ‫ومتى كنا ضمن نمط مقاطعة التطبيق فإن هناك الكثير من التقنيات التي يمكننا استخدام معظمها في تحليل‬ ‫شيفرتنا ومعرفة الحالة الفعلية لتطبيقنا عند النقطة التي توقفنا عندها‪.‬‬ ‫إن مراقبة محتوى المتحوالت ليس إال مثاال واحدا لما يمكن أن يقدمه لنا ‪ VS‬من مساعدة كبرى لجعل‬ ‫األمور بسيطة قدر المستطاع والطريقة األ بسط للتحقيق من قيمة متحول هي بتحريك مشيرة الفارة فوق‬ ‫اسم المتحول في الشيفرة البرمجية وذلك طبعا ضمن نمط المقاطعة سيظهر ع ندئذ تلميح ضمن إطار‬ ‫يعرض معلومات عن المتحول باإلضافة إلى القيمة التي يأخذها المتحول حاليا يمكننا أن نرى ذلك كما في‬ ‫الشكل (‪:)7-14‬‬ ‫الشكل (‪)7.‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪207 -‬‬ ‫‪-‬‬ .‬‬ ‫والن ربما قد الحظت اننا عندما ننفذ تطبيقا من خالل ‪ VS‬فإن هناك تغيرا في عدد من إطارات ‪VS‬‬ ‫وبصورة افتراضية إليك ما سيحدث أثناء تنفيذ التطبيق‪:‬‬ ‫‪ ‬اختفاء إطار الخصائص ‪.Properties‬‬ ‫‪ ‬تغير حجم إطار ‪ Output‬حيث سيحتل نصف الجزء السفلي من الشاشة وظهور إطار جديد إن‬ ‫اإلطار الجديد الذي سيظهر في زمن تنفيذ المشروع مفيد جدا لعمليات التنقيح فهو يسمح بتتبع‬ ‫ومراقبة قيم المتحوالت في تطبيقنا عند مقاطعة التنفيذ ويتضمن هذا اإلطار ثالثة بنود‪:‬‬ ‫‪ o‬البند ‪ :Autos‬ح يث يستعرض المتحوالت المستخدمة في التعليمات الحالية‪.14‬‬ ‫ويمكننا أيضا أن نركز على تعابير كاملة وليس مجرد متحول للحصول على معلومات حول نتائج هذه‬ ‫التعابير وبنفس الطريقة إن هذه التقنية محددة نوعا ما فهي ال تمكننا من استعراض محتوى مصفوفة على‬ ‫سبيل المثال‪.‫إن تلك ليست بشيفرة سهلة يمكنك فهمها كشيفرة ‪ C#‬وليس هناك أمل في فهم هذه التعليمات إال من قبل‬ ‫خبراء بلغة التجميع هذا يعني أن شيفرتنا البرمجية محمية من معظم عيون المتطفلين‪.

15‬‬ ‫تعمل جميع هذه اإلطارات بنفس المبدأ تقريبا مع بعض المزايا اإلضافية لكل إطار وذلك باالعتماد على‬ ‫وظيفة اإلطار وبصورة عامة فإن كل إطار يتضمن الئحة من المتحوالت تشتمل على المعلومات التالية‪:‬‬ ‫اسم المتحول‪ ،‬قيمة المتحول‪ ،‬ونوع هذا المتحول‪ .‫‪ o‬البند ‪ :Watch N‬تخصيص عدد من المتحوالت والتعابير لمراقبتها حيث تتراوح ‪ N‬بين‬ ‫‪ 1‬و ‪ 4‬إليك الشكل االفتراضي للشاشة في زمن تنفيذ المشروع الشكل (‪:)7-15‬‬ ‫الشكل (‪)7.‬أما بالنسبة لمتحوالت أكثر تعقيدا كالمصفوفات فإنها قد‬ ‫تتضمن معلومات إضافية يمكننا استعراضها أو طيها بالنقر على رمز السهم األفقي أو رمز السهم المائل‬ ‫المجاور السم المتحول على سبيل المثال يبين الشكل (‪ )7-16‬إطار تتبع المتحوالت‪ :‬البند ‪ Locals‬الناتج‬ ‫عن وضع نقطة مقاطعة في شيفرة ا لتطبيق السابق بعد استدعاء التابع )(‪ Maxima‬مباشرة‪:‬‬ ‫الشكل (‪)7.)maxValIndices‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪208 -‬‬ ‫‪-‬‬ .16‬‬ ‫الحظ هنا كيفية عرض متحوالت المصفوفات (لقد قمت بتوسعة المصفوفة ‪.

‫يمكننا تعديل محتوى المتحوالت بواسطة هذا اإلطار أيضا وعند قيامنا بذلك فإننا سنتجاوز أي إسناد لهذه‬ ‫المتحوالت يمكن أ ن يحدث ضمن الشيفرة وللقيام بذلك فإننا ببساطة سنكتب القيمة الجديدة ضمن عمود‬ ‫‪ value‬للمتحول الذي نود تغيير قيمته‪.‬‬ ‫هناك نقطة أخيرة يجب أن نذكرها قبل إنهاء حديثنا عن إطارات ‪ Watch‬وهي أننا لسنا بحاجة إلضافة‬ ‫المتحوالت أو التعابير إلى إطار ‪ Watch‬في كل مرة نقوم فيها بتنفيذ التطبيق فسوف يتذكر ‪VS‬‬ ‫المتحوالت التي طلبنا مراقبتها وذلك لمراقبتها عند التنفيذ التالي للشيفرة‪.‬‬ ‫أما البند ‪ Watch‬فإنه يمكننا من مراقبة متحوالت أو تعابير محددة والستخدام ها اإلطار فإننا سنكتب اسم‬ ‫المتحول أو التعبير ضمن عمود ‪ Name‬ومن ثم سنلحظ ا لنتائج الحظ أنه ال يمكن لجميع المتحوالت‬ ‫الموجودة في التطبيق أن تكون ضمن المدى دائما على سبيل المثال يبين الشكل (‪ )7-17‬إطار ‪Watch‬‬ ‫لعدد من المتحوالت والتعابير ولقد استخدمنا شيفرة المثال األخير هنا أيضا وقد قاطعنا تنفيذ التابع‬ ‫)(‪:Maxima‬‬ ‫الشكل (‪)7.‬‬ ‫يمكننا أن نضيف المتحوالت إلى إطار ‪ Watch‬بسحب اسم المتحول من الشيفرة المصدرية وإسقاطه‬ ‫ضمن اإلطار‪.17‬‬ ‫إن المصفوفة )( ‪ testArray‬هي مصفوفة محلية بالنسبة للتابع )( ‪ Main‬وال يمكننا أن نرى قيمة لها هنا‬ ‫وبدال من ذلك فإننا سنحصل على رسالة خطأ تبين أن المتحول خارج المدى‪.‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪209 -‬‬ ‫‪-‬‬ .‬‬ ‫ولكي نضيف إطارات أخرى فإننا سنستخدم األمر ‪ Watch N‬من القائمة الفرعية ‪ Watch‬من‬ ‫‪ Windows‬من القائمة ‪ Debug‬حيث يمكننا أن نستخدم أربعة إطارات ‪ Watch‬كحد أقصى وبأمر‬ ‫القائمة هذا يمكننا أن ننتقل بين هذه اإلطارات فكل إطار يمكن أن يتضمن على مجموعة منفردة من‬ ‫المتحوالت وال تعابير لمراقبتها وبالتالي يمكننا تجميع المتحوالت المرتبطة مع بعضها البعض للوصول‬ ‫إليها بسهولة وباإلضافة إلى إطارات ‪ Watch‬األربعة تلك فإن هناك اإلطار ‪ QuickWatch‬أيضا والذي‬ ‫يعطينا معلومات تفصيلية عن متحول في الشيفرة المصدرية بسرعة والستخدام هذا اإلطار فإننا سننقر‬ ‫بزر الفأرة األيمن على المتحول ونختار االمر ‪ QuickWatch‬من القائمة المنسدلة‪.

‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪210 -‬‬ ‫‪-‬‬ .‬‬ ‫عند الدخول في نمط المقاطعة سيظهر سهم على اليسار محرر الشيفرة عند السطر الذي يوشك على أن‬ ‫بنفذ يمكن أن يظهر بشكل أولي ضمن الدائرة الحمراء لنقطة المقاطعة هذا إن استخدمت نقطة مقاطعة‬ ‫للدخول في نمط مقاطعة التنفيذ‪:‬‬ ‫الشكل (‪)7.‬‬ ‫زر ‪ Step Out‬تنفيذ األسطر البرمجية إلى نهاية الكتلة البرمجية واالستمرار في نمط المقاطعة‬ ‫عند التعليمة التي تلي هذه الكتلة البرمجية‪.18‬‬ ‫يمكننا هنا رؤية النقط ة التي وصل التنفيذ عندها أثناء دخولنا لنمط المقاطعة وعند هذه النقطة يمكننا أن‬ ‫نختار االستمرار بالتنفيذ سطرا بسطر وللقيام بذلك فإننا نستخدم أزرار شريط أدوات ‪ Debug‬الذي تعرفنا‬ ‫عليه في السابق وكما تشير األسهم فإن بإمكاننا ان نتحكم في سير التطبيق وهو في نمط المقاطعة بواسطة‬ ‫هذه األيقونات الثالث وهي‪:‬‬ ‫زر ‪ Step Into‬حيث سيتم تنفيذ السطر الحالي واالنتقال على السطر التالي لتنفيذه‪.‫لقد رأينا ما يحدث في تطبيقنا عند النقطة التي يدخل فيها نمط المقاطعة واآلن سوف نرى كيف نستخدم‬ ‫‪ VS‬للخطو خالل الشيفرة أثناء مقاطعة التنفيذ مما يسمح لنا برؤية النتائج الحالية للشيفرة المنفذة‪.‬‬ ‫فإن أردنا ان نتفحص كل عملية يقوم بها التطبيق فغننا سنستخدم ‪ Step Into‬لتتبع تنفيذ التعليمات واحدة‬ ‫تلو األخرى عن هذا يتضمن االنتقال إلى داخل التوابع كالتابع )(‪ Maxima‬مثال وبالنقر على هذه االيقونة‬ ‫عند وصول السهم على استدعاء التابع )(‪ Maxima‬سيؤدي ذلك النتقال السهم على اول سطر في التابع‬ ‫)(‪ Maxima‬اما بالنقر على ‪ Step Over‬عند هذا السطر فسيتم نقل السهم على السطر الذي يلي استدعاء‬ ‫التابع )(‪ Maxima‬دون الدخول إلى شيفرة التابع )(‪ Maxima‬وإن خطونا ضمن التا بع ال نود ان نراقب‬ ‫ما يجث ضمنه يمكننا ببساطة ان نضغط على ‪ Step Out‬حيث سنعود على الشيفرة التي استدعت هذا‬ ‫التابع‪.‬‬ ‫زر ‪ Step Over‬كما في الزر السابق إال اننا لن ندخل في الكتل البرمجية المعششة‪.

Immediate Window‬‬ ‫اإلطار ‪ Command window‬يسمح لنا بالقيام بوظائف وعمليات ‪ VS‬دون استخدام األدوات او القوائم‬ ‫وأما اإلطار ‪ Immediate Window‬فهو يسمح لنا بتنفيذ شيفرة ضمن الشيفرة الموجودة في الملف‬ ‫المنفذ حاليا ستالحظ وجود الرمز )>( عندما نكون ضمن إطار ‪ Command Window‬وذلك عند بداية‬ ‫كل سطر في هذا اإلطار يمكننا أن ننتقل إلى إطار ‪ Immediate Window‬من إطار ‪Command‬‬ ‫‪ window‬بكتابة ‪ immed‬في هذا اإلطار والضغط على مفتاح ‪ Enter‬أما عندما نكون ضمن إطار‬ ‫‪ Immediate Window‬ونريد الذهاب لإلطار ‪ Command window‬فإننا نقوم بكتابة )‪(>cmd‬‬ ‫ضمن اإلطار ‪ Command window‬والضغط على مفتاح ‪ Enter‬طبعا يمكنك استخدام الفارة للتنقل‬ ‫بين اإلطارين وللتذكير هذين اإلطارين يعمالن في حالة التنقيح فقط‪.‬‬ ‫سوف نركز على إطار ‪ Immediate Window‬هنا وذلك ألن اإلطار ‪ Command window‬مفيد‬ ‫فقط بالنسبة للتعابير المعقدة الطريقة االبسط الستخدام هذا اإلطار هو بتنفيذ التعابير وللقيام بذلك فإننا‬ ‫سنكتب التعبير مباشرة ثم نضغط على مفتاح ‪ Enter‬ستظهر المعلومات المطلوبة عندئذ على سبيل المثال‬ ‫انظر الشكل (‪:)7-19‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪211 -‬‬ ‫‪-‬‬ .‬‬ ‫ومع تخطينا ألسطر الشيفرة البرمجية وانتقالنا من سطر إلى آخر فإن هناك احتماال لتغيير قيم المتحوالت‬ ‫في هذه الشيفرة وبتتبع وتفحص اإلطارات التي تحدثنا عنا مسبقا يمكننا أن نرى ما يحدث في تطبيقنا‬ ‫بسهولة‪.‬‬ ‫هناك بضعة إطارات أخرى لم نتحدث عنها بعد فهناك عدة إطارات تظهر ضمن إطار ‪Task‬‬ ‫‪ List/Output‬خالل التنقيح وهما إطار ‪ Command Window‬وإطار ‪ Call Stack‬وإطار‬ ‫‪ Breakpoints‬وإطار ‪.‬‬ ‫عندما نواجه شيفرة يشتبه في وجود أخطاء ضمنها تصبح هذه التقنية األكثر أهمية هنا يمكننا ان نخطو‬ ‫ضمن الشيفرة إلى النقطة التي نتوقع حصول المشاكل عندها حيث ستولد األخطاء تماما كما لو اننا ننفذ‬ ‫البرنامج بص ورة عادية وخالل ذلك يمكننا ان نتتبع البيانات لرؤية ما يسير بصورة خاطئة سوف نستخدم‬ ‫هذه التقنية الحقا في هذا الفصل وذلك لرؤية ما يحدث في التطبيق‪. ‫مالحظة‪:‬‬ ‫انتبه من ان تختلط عليك األمور فتنفيذ الشيفرة له عالقة بالخطو هنا وإن ما سيحدث هنا هو فقط‬ ‫ت حديد إيقاع معين للدخول في نمط المقاطعة ليس أكثر‪.

‫الشكل (‪)7.19‬‬ ‫و في معظم الحاالت فإننا سنستفيد من إطارات مراقبة المتحوالت اإلطار ‪ Watch‬أكثر من هذا اإلطار‬ ‫إال أن هذه التقنية تبقى مفيدة أحيانا وذلك الختبار التعابير مثال‪.‬‬ ‫اإلطار األخير الذي سنتناوله هنا يستعرض لنا النقطة التي وصلنا عندها أثناء تنفيذ التطبيق وبصورة‬ ‫أبسط فإن هذا اإلطار يبين لنا التابع الذي يجري تنفيذه حاليا باإلضافة إلى التابع الذي قام باستدعائه والتابع‬ ‫الذي استدعى ذلك التابع أيضا وهكذا وبالتالي فغننا سنحصل على قائمة شجرية من استدعاءات التوابع‬ ‫تسمى بمكدس االستدعاءات وسيتم تحديد النقطة التي حدث عندها استدعاء التابع أيضا‪.29‬‬ ‫إن هذا اإلطار مفيد جدا عند المرحلة األولية الستكشاف األخطاء باعتبار أنه يسمح لنا برؤية ما يحدث‬ ‫قبل حدوث الخطأ مباشرة وذلك باعتبار أن معظم األخطاء تحدث ضمن التوابع مما سيساعدنا على تحديد‬ ‫مصدر الخطأ أي التابع الذي حصل عنه الخطأ‪.‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪212 -‬‬ ‫‪-‬‬ .‬‬ ‫وفي مثالنا السابق إذا دخلنا نمط المقاطعة في التابع )(‪ Maxima‬أو باالنتقال إلى هذا التابع باستخدام تقنية‬ ‫تخطي الشيفرة فسيؤدي ذلك إلى ظهور النتائج التالية على إطار ‪:Call Stack‬‬ ‫الشكل (‪)7.

‬‬ ‫يمثل االعتراض خطأ حدث أثناء تنفيذ التطبيق وتم توليده إما من شيفرتنا أو من تابع استدعته شيفرتنا إن‬ ‫وصف الخطأ هنا أكثر غموضا من الوصف ا لذي استخدمناه مسبقا وذلك ألن االعتراضات يمكن أن تولد‬ ‫بصورة يدوية في التوابع إلى غير ذلك من أمور على سبيل المثال يمكننا أن نولد اعتراضا في تابع إذا لم‬ ‫يبدأ أحد البارامترات النصية لتابع بالحرف ”‪ “a‬إن هذا ال يمثل خطأ بحد ذاته وإنما وبحكم سياق ومنطق‬ ‫التطبيق فإ ننا سنتعامل مع حاالت كهذه على أنها تمثل خطأ‪. 4.‬‬ ‫لقد تناولنا االعتراضات عددا من المرات في هذا الكتاب ولربما أبسط مثال لذلك هو عند محاولة اإلشارة‬ ‫إلى عنوان عنصر في مصفوفة خارج مجالها على سبيل المثال‪:‬‬ ‫.‬‬ ‫لقد تعلمنا في الجزء األول من هذا الفصل كيفية اكتشاف األخطاء وتصحيحها خالل تطوير التطبيق وذلك‬ ‫باعتبار أنها لن تحدث في مرحلة اإلطالق (أي عندما يصل التطبيق أليدي المستخدمين) لكن هناك حاالت‬ ‫يمكننا أن نقدر حدوث األخطاء عندها وليس هناك أي طريقة نضمن بها عدم حدوث األخطاء ‪100%‬‬ ‫وفي حاالت كهذه فإنه لمن األفضل أن نعالج هذه األخطاء وأن نكتب شيفرة قوية بالصورة التي يمكنها أن‬ ‫تتعامل مع هذه األخطاء بصورة مثمرة دون مقاطعة تنفيذ التطبيق بصورة مزعجة للمستخدم‪. 7. 2‬‬ ‫.} ‪int[] myArray = { 4. ‫مالحظة‪:‬‬ ‫الحظ ان هذا اإلطار يمكن أن يعرض معلومات مركبة فيمكن مثال أن يحدث الخطأ خارج التطبيق‬ ‫على سبيل المثال كاستخدام توابع خارجية بصورة خاطئة وفي حاالت كهذه فإنك ستجد الئحة‬ ‫طويلة من المعلومات في هذا اإلطار‪.]‪int myElem=myArray[4‬‬ ‫سيولد ذلك رسالة اعتراض وسيتوقف التطبيق عندها بالرسالة الشكل (‪:)7-21‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪213 -‬‬ ‫‪-‬‬ .

finally‬إن كل كلمة من هذه الكلمات لها كتلة برمجية ويجب أن تستخدم هذه الكلمات الثالث‬ ‫بصورة متعاقبة وبترتيب ثابت والبنية األساسية لهذه الصيغة هي كما يلي‪:‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪214 -‬‬ ‫‪-‬‬ .myArray‬‬ ‫ال تظهر هذه الرسالة وال يتوقف التطبيق عن العمل إال إذا لم يكن االعتراض معالجا إذن ماذا علينا ان‬ ‫نفعل لكي نتمكن من معالجة االعتراضات؟‬ ‫تتضمن لغة ‪ C#‬صيغة لمعالجة االعتراضات البنيوية ‪ Structured Exception Handling‬أو‬ ‫اختصار ‪ SHE‬وهي عبارة عن كلمات مفتاحية تستخدم لإلشارة إلى أن الشيفرة قابلة لمعالجة‬ ‫االعتراضات مضمنة إياها تعليمات ستنفذ عند حدوث اعتراض ما إن هذه الكلمات الثالث هي‬ ‫‪ try.IndexOutOfRangeException‬ومن‬ ‫خالل هذا االسم يمكننا أن نستك شف ان الخطأ نتج عن استخدام دليل خارج المجال الممكن للمصفوفة‬ ‫‪.catch. ‫الشكل (‪)7.21‬‬ ‫تعرف االعتراضات في فضاءات األسماء ولمعظمها أسماء تدل على معانيها على سبيل المثال إن‬ ‫االعتراض المولد في الشيفرة السابقة يأخذ االسم ‪ System.

‬‬ ‫الكتلة ‪ catch‬وتتضمن الشيفرة التي ستنفذ عند رمي االعتراضات يمكن أن تعد كتل ‪catch‬‬ ‫بطريقة تستجيب عندها ألنواع اعتراضات محددة مثل االستجابة لالعتراض‬ ‫‪ System.‬‬ ‫الكتلة ‪ try‬تتضمن الشيفرة التي يمكن ان تتسبب برمي االعتراضات حيث تعني الكلمة رمي‬ ‫‪ throw‬في لغة ‪ C#‬توليد الخطأ أو الشيفرة المتسببة في حدوث الخطأ‪.IndexOutOfRangeException‬فقط وذلك بتحديد نوع االعتراض ضمن‬ ‫>‪ <exceptionType‬حيث يمكننا توفير عدة كتل ‪ catch‬تعالج كل واحدة منها نوعا من‬ ‫االعتراضات أو األخطاء ومن الممكن تجاهل البارامتر وفي حالة كهذه فإنه يكون لدينا كتل‬ ‫‪ catch‬عامة تستجيب لجميع االعتراضات‪..‬‬ ‫}‬ ‫‪Finally‬‬ ‫{‬ ‫‪.‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪215 -‬‬ ‫‪-‬‬ . ‫‪Try‬‬ ‫{‬ ‫‪..‬‬ ‫الكتلة ‪ finally‬والتي تتضمن الشيفرة التي ستنفذ دوما سواء بعد الكتلة ‪ try‬إذا لم يحدث أي‬ ‫اعتراض أو بعد الكتلة ‪ catch‬عند حدوث االعتراض ومعالجته ضمنها أو قبل أن ينهي‬ ‫االعتراض غير المعالج تنفيذ التطبيق‪.‬‬ ‫}‬ ‫ومن الممكن أن تكون هناك كتلة ‪ try‬وكتلة ‪ finally‬فقط دون وجود الكتلة ‪ catch‬أو أن يكون هناك كتلة‬ ‫‪ try‬وعدة كتل ‪ catch‬فإن كان هناك كتلة أو أكثر من كتل ‪ catch‬عندئذ فإن وجود الكتلة ‪ finally‬هو‬ ‫أمر اختياري وإال فإن وجودها إجباري‪..‬‬ ‫)‪Catch (<exceptionType> e‬‬ ‫{‬ ‫‪.

‪System.Text‬‬ ‫‪using‬‬ ‫.WriteLine("Not throwing an exception.)‪Console.Threading. exceptionType‬‬ ‫)‪switch (exceptionType‬‬ ‫{‬ ‫‪case "none":‬‬ ‫.‬‬ ‫‪ ‬وإن طابقت كتلة ‪ catch‬نوع االعتراض الحاصل عندئذ سيتم تنفيذ شيفرة هذه الكتلة ومن ثم تنفيذ‬ ‫شيفرة الكتلة ‪ finally‬إن وجدت هذه الكتلة في تلك الحالة‪.Exception.‬‬ ‫. "index".‪System. ‫مالحظة‪:‬‬ ‫في الحقيقة إن تنفيذ كتلة ‪ finally‬قبل إنهاء تنفيذ التطبيق نتيجة اعتراض غير معالج هو‬ ‫السبب الرئيسي لوجود الكلمة ‪ finally‬وذلك باعتبار أنه يمكننا ان نضع الشيفرة بعد صيغة‬ ‫‪ SHE‬بصورة مباشرة لكي تنفذ‪.Generic‬‬ ‫‪using‬‬ ‫.‬‬ ‫أما تسلسل األحداث الذي يمكن أن يحدث بعد حدوث االعتراض في الشيفرة ضمن الكتلة ‪ try‬فهو كما‬ ‫يلي‪:‬‬ ‫‪ ‬سيتوقف تنفيذ الكتلة ‪ try‬عند النقطة التي حدث عندها االعتراض‪.‬‬ ‫‪ ‬سيتم البحث عن كتل ‪ catch‬المخصصة لمعالجة االعتراض الحاصل حيث سيتم تفحص ما إذا‬ ‫كانت أحد هذه الكتل مطابقة لنوع االعتراض الذي رمي فإن لم تتوفر هناك كتل ‪ catch‬موافقة‬ ‫لهذا االعتراض سيتم تنفيذ الشيفرة الموجودة في الكتلة ‪ finally‬وهو ما يعلل وجوب وجود الكتلة‬ ‫‪ finally‬عند عدم توفر كتلة ‪ catch‬موافقة لنوع االعتراض الحاصل‪.)"‪Console.)"‪Console.‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪216 -‬‬ ‫‪-‬‬ .Console TryCatchFinally‬‬ ‫‪ -2‬أضف الشيفرة البرمجية التالية إلى محرر نصوص ‪ C#‬في ‪:class Program‬‬ ‫‪using‬‬ ‫. "simple".} "‪static string[] eTypes = { "none".‪System.".‪System.‪System‬‬ ‫‪using‬‬ ‫.‪break‬‬ ‫‪//line21‬‬ ‫‪case "simple":‬‬ ‫.‬‬ ‫لقد حان الوقت اآلن لكي نتناول مثاال يستعرض كيفية معالجة االعتراضات‪:‬‬ ‫تطبيق حول كتابة نص في نافذة الخرج‪:‬‬ ‫‪ -1‬قم بإنشاء تطبيق ‪ Console‬جديد باسم ‪.Collections. "nested index‬‬ ‫)‪static void ThrowException(string exceptionType‬‬ ‫{‬ ‫‪//line14‬‬ ‫.Linq‬‬ ‫‪using‬‬ ‫.Tasks‬‬ ‫‪namespace Console_TryCatchFinally‬‬ ‫{‬ ‫‪class Program‬‬ ‫{‬ ‫.WriteLine("ThrowException(\"{0}\")reached.WriteLine("Throwing System.

"). e.WriteLine(). ‫ املهندس حسام الدين الرز‬:‫إعداد‬ 217 - - . } catch //line72 { Console." ."). } Console.IndexOutOfRangeException" + "catch" + "block reached Message:\n\"{0}\"". Console.").WriteLine("ThrowException(\"nested index\")" + "general catch block reached. throw (new System. eType).WriteLine("Main() System .//line60 Console. eTypes[4] = "error". case "index": Console.WriteLine("Main() genral catch block reached.WriteLine("ThrowException(\"nested index\")" + "try block reached.").WriteLine("ThrowException(\"index\")called. } finally { Console. //line25 break. } finally { Console.WriteLine("ThrowException(\"{0}\")called.//line61 ThrowException(eType).WriteLine("ThrowException(\"nested index\")" + "finally block reached.WriteLine("Throwing" + "System . } } static void Main(string[] args) { foreach (string eType in eTypes) { try { Console. Console.Exception()).WriteLine("Maine() try block reached"). case "nested index": try //line33 { Console.WriteLine("Main() finally block reached.Message).WriteLine("Main() try block continues.//line64 } catch (System."). //line38 } catch //line40 { Console.").IndexOutOfRangeException. ThrowException("index").IndexOutOfRangeException e)//line66 { Console.")."). //line30 break. } break.

‬‬ ‫أي سيتم التصرف بحسب البارامتر الممرر وذلك وفقا لما يلي‪:‬‬ ‫‪ ‬االستدعاء )”‪ ThrowException(“none‬لن يؤدي إلى رمي أي اعتراض‪.IndexOutOfRangeException‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪218 -‬‬ ‫‪-‬‬ .‬‬ ‫‪ ‬االستدعاء )”‪ ThrowException(“simple‬سيولد اعتراضا عاما‪.System.)7-22‬‬ ‫الشكل (‪)7-22‬‬ ‫كيفية العمل‪:‬‬ ‫‪How it Works:‬‬ ‫لهذا التطبيق كتلة ‪ try‬في التابع )(‪ Main‬الذي يستدعي التابع )(‪ ThrowException‬ويمكن لهذا التابع‬ ‫أن يرمي اعتراضات وذلك بحسب البارامتر الممرر إليه‪.‬‬ ‫‪ ‬االستدعاء )”‪ ThrowException(“index‬سيولد االعتراض‬ ‫‪. ‫}‬ ‫}‬ ‫}‬ ‫}‬ ‫‪ -3‬نفذ التطبيق في نمط التنقيح باختيار األمر ‪ Start without Debugging‬أو بالضغط على مفتاح‬ ‫‪ Ctrl+ F5‬فيظهر الشكل (‪.

System.‫‪ ‬االستدعاء )”‪ ThrowException(“nested index‬يتضمن على كتلة ‪ try‬خاصة به والتي‬ ‫تتضمن شيفرة تقوم باستدعاء )”‪ ThrowException(“index‬والذي سيولد االعتراض‬ ‫‪.WriteLine("Maine() try block reached‬‬ ‫مالحظة‪:‬‬ ‫الحظ أنني سأشير إلى الشيفرة وفقا ألرقام األسطر والتي تظهر ضمن الشيفرة الموجودة في‬ ‫الكتاب على هيئة تعليقات من الشكل ‪.Debug‬‬ ‫ما أن تنفذ التطبيق حتى يدخل في نمط المقاطعة مباشرة حيث سيظهر سهم عند السطر رقم ‪ 69‬وإذا‬ ‫اخترت البند ‪ Locals‬في إطار مراقبة المتحوالت ستجد أن قيمة ‪ eType‬الحالية هي ‪ none‬استخدم‬ ‫األيقونة ‪ Step Into‬لتنفيذ األسطر ‪ 60‬و‪ 61‬ومن ثم تفحص السطر األول من النص الذي تمت طباعته‬ ‫على نافذة ‪ Console‬بعد ذلك استخدم األيقونة ‪ Step Into‬مرة أخرى لالنتقال إلى استدعاء التابع‬ ‫)(‪ ThrowException‬على السطر ‪.63‬‬ ‫ومتى انتقل التنفيذ إلى التابع )(‪ ThrowException‬في السطر رقم ستتغير محتويات اإلطار ‪Locals‬‬ ‫حيث لم يعد المتحوالن ‪ args‬أو ‪ eType‬ضمن المدى فهما متحوالن محليان للتابع )(‪ Main‬وبدال منهما‬ ‫سنجد المتحول المحلي ‪ exceptionType‬وهو بارامتر ا لتابع حيث يعامل كالمتحول المحلي في هذا‬ ‫التابع وهو يأخذ القيمة ‪ none‬طبعا استمر بالضغط على أيقونة ‪ Step Into‬إلى ان تصل إلى تعليمة‬ ‫‪ switch‬التي تتفحص قيمة ‪ exceptionType‬وتنفيذ الشيفرة التي ستقوم بطباعة النص‪Not :‬‬ ‫‪ throwing an exception‬على الشاشة وعند تنفيذ تعليمة ‪ break‬في السطر رقم ‪ 21‬سيتم الخروج‬ ‫من التابع واالستمرار في تنفيذ التابع )(‪ Main‬في السطر رقم ‪ 69‬الحظ أنه لم يتم رمي أي اعتراض‬ ‫وبالتالي سيستمر التنفيذ في كتلة ‪.try‬‬ ‫بعد ذلك سيستمر التنفيذ مع الكتلة ‪ finally‬استمر بالنقر على أيقونة ‪ Step Into‬عددا من المرات إلنهاء‬ ‫تنفيذ كتلة ‪ finally‬والدورة األولى لحلقة ‪ foreach‬وعند الوصول التالي للسطر رقم ‪ 69‬سيتم استدعاء‬ ‫التابع )(‪ ThrowException‬ببارامتر جديد هو ‪.‬‬ ‫قم بإضافة نقطة مقاطعة عند السطر رقم ‪ 69‬الذي يتضمن على التعليمة‪:‬‬ ‫.//Line xx‬‬ ‫نفذ التطبيق في نمط التنقيح ‪.simple‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪219 -‬‬ ‫‪-‬‬ .IndexOutOfRangeException‬‬ ‫إن كل قيمة نصية من قيم البارامتر مخزنة ضمن المصفوفة العامة ‪ eTypes‬حيث سيتم المرور خالل‬ ‫هذه المصفوفة واستدعاء التابع )(‪ ThrowException‬مرة واحدة وفقا لهذه القيم النصية وخالل ذلك‬ ‫سيتم طباعة عدد من الرسائل على نافذة ‪ Console‬لإلشارة إلى ما يحدث‪.)"‪Console.‬‬ ‫تعطي هذه الشيفرة فرصة مناسبة الستخدام تقنيات الخطو التي رأيناها في هذا الفصل فباالنتقال سطرا‬ ‫بسطر خالل هذه الشيفرة يمكننا أن نلحظ كيفية توليد أو رمي االعتراضات‪.

))(‪throw (new System.IndexOutOfRangeException‬‬ ‫وفي هذه المرة هناك كتلة ‪ catch‬مطابقة في التابع )(‪ Main‬وبالخطو ضمن الشيفرة سننتقل إلى هذه‬ ‫الكتلة التي تبدأ بالسطر رقم ‪.‫وباالستمرار في الضغط على االيقونة ‪ Step Into‬خالل التابع )(‪ ThrowException‬ستالحظ أننا‬ ‫وصلنا بعد عدد من النقرا ت على ايقونة ‪ Step Into‬إلى السطر رقم ‪.WriteLine‬في هذه الكتلة بطباعة رسالة مخزنة ضمن االعتراض وذلك‬ ‫باستخدام القيمة ‪ e.index‬‬ ‫وفي هذه المرة سيولد التابع )(‪ ThrowException‬اعتراضا في السطر رقم ‪:39‬‬ ‫"‪eTypes[4] = "error‬‬ ‫إن المصفوفة ‪ eTypes‬هي مصفوفة عامة وبالتالي يمكننا الوصول إليها من ضمن أي تابع في هذا الملف‬ ‫لكننا هنا نحاول الوصول إلى العنصر الخامس في المصفوفة تذكر أن ترقيم العناصر يبدا من الصفر وهو‬ ‫ما سيولد االعتراض ‪.Exception‬‬ ‫لقد استخدمنا الكلمة ‪ throw‬لتوليد اعتراض بصورة يدوية والحظ أننا هنا قمنا بتوليد اعتراض جديد‬ ‫باستخدام الكلمة ‪ new‬بتحديد ذلك كبارامتر لهذه الكلمة لقد استخدمنا هنا اعتراضا آخر من فضاء األسماء‬ ‫‪.66‬‬ ‫يقوم التابع )(‪ Console.finally‬الموجودة ضمن التابع )(‪ ThrowException‬وليس‬ ‫لهذه البنية تطابق صريح من نوع االعتراض الحاصل وبالتالي سيتم تنفيذ كتلة ‪ catch‬العامة بدء بالسطر‬ ‫رقم ‪ 72‬وسيستمر التنفيذ ضمن الكتلة ‪ catch‬إلى الكتلة ‪ finally‬أيضا إلى الوصول لنهاية التابع‬ ‫المستدعى‪.Message‬يمكننا التعامل مع االعتراض الحاصل عبر بارامتر الكتلة ‪ catch‬وبتخطي‬ ‫هذه الشيفرة باستخدام ‪ Step Into‬سنجد أنفسننا ضمن الكتلة ‪ finally‬وليس ضمن كتلة ‪ catch‬الثانية‬ ‫وذلك ألنه قد تمت معالجة االعتراض في كتلة ‪ catch‬ومن ثم العودة إلى دورة الحلقة في )(‪ Main‬من‬ ‫جديد واستدعاء التابع )(‪ ThrowException‬مجددا في السطر رقم ‪.69‬‬ ‫وعند الوصول إلى بنية ‪ switch‬في التابع )(‪ ThrowException‬فإننا سندخل هذه المرة في كتلة ‪try‬‬ ‫جديدة بدء بالسطر رقم ‪ 33‬وعند الوصول إلى السطر رقم ‪ 38‬سنقوم باستدعاء تعاودي ذاتي للتابع‬ ‫)(‪ ThrowException‬أيضا وهذه المرة بالبارامتر ‪ index‬وإذا أحببت يمكنك استخدام الزر ‪Step‬‬ ‫‪ Over‬لتخطي أسطر الشيفرة التي ستنفذ هنا باعتبار أننا اطلعنا عليها وكما رأينا مسبقا فإن هذا االستدعاء‬ ‫سيولد اعتراضا من النوع ‪ System.Exception‬‬ ‫وعندما تنفيذ هذه التعليمة في نمط ‪ Step Info‬سنجد أنفسنا ضمن كتلة ‪ catch‬العامة الموجودة في السطر‬ ‫رقم ‪ 72‬فليس هناك أي كتلة ‪ catch‬مطابقة لهذا النوع من االعتراضات وبالتالي سيتم تنفيذ كتلة ‪catch‬‬ ‫العامة وبالخطو خالل شيفرة كتلة ‪ catch‬وصوال للكتلة ‪ finally‬والعودة إلى دورة الحلقة التي استدعت‬ ‫التابع )(‪ ThrowException‬بالبارامتر ‪ simple‬في السطر رقم ‪ 69‬وهذه المرة فإن البارامتر الممرر‬ ‫للتابع )(‪ ThrowException‬هو ‪.‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪220 -‬‬ ‫‪-‬‬ .catch.System.System..IndexOutOfRangeException‬وهذه المرة سيتم معالجة هذا‬ ‫االعتراض باستخدام البنية ‪ try.25‬‬ ‫..

Ctrl+Alt+E‬‬ ‫الشكل (‪)7-23‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪221 -‬‬ ‫‪-‬‬ .‫هناك أمر مهم هنا فعلى الرغم من أن االعتراض قد رمى في التابع )(‪ Main‬إال أنه قد تمت معالجته‬ ‫ضمن التابع )(‪ ThrowException‬وهذا يعني أنه ليس هناك أية اعتراضات لمعالجتها في التابع‬ ‫)(‪ Main‬لذا سينتقل التنفيذ مباشرة إلى الكتلة ‪ finally‬ثم سينتهي تنفيذ التطبيق بعد ذلك‪.NET‬عددا كبيرا من أنواع االعتراضات ويمكننا رمي ومعالجة أي من هذه‬ ‫االعتراضات بحرية ضمن شيفرتنا البرمجية يقدم ‪ Visual Studio 2013‬صندوق حوار لتفحص‬ ‫وتحرير االعتراضات المتوفرة ويمكننا عرض صندوق الحوار هذا باختيار ‪ Exceptions‬من القائمة‬ ‫‪ Debug‬أو بالضغط على المفاتيح ‪.‬‬ ‫مالحظة‪:‬‬ ‫الحظ أنه عند تنفيذ هذه الشيفرة سيظهر لنا بند ضمن قائمة المهام في إطار ‪ Task List‬يشير‬ ‫إلى أن هناك تعليمة ضمن السطر ال يمكن الوصول إليها تلك التعليمة هي ‪ break‬وهذا منطقي‬ ‫باعتبار ان االعتراض سيرمى باستخدام األمر ‪ throw‬والذي سيؤدي إلى كتلة ‪ catch‬أو‬ ‫‪ finally‬مباشرة‪.‬‬ ‫يتضمن إطار عمل ‪ .

‬‬ ‫يمكننا اعداد االعتراضات باستخدام زر الخيار في أسفل النافذة فمعظم هذه االعتراضات معدة بالخيار‬ ‫‪ Use parent setting‬بصورة افتراضية وهذا يعني أنها تستخدم خيارا ت مستوى الصنف الذي تنتمي‬ ‫إليه يمكننا أن نستخدم مجموعات الخيارات األولى وهو ‪ When the exception is thrown‬لتحديد‬ ‫كيف سيتم التصرف عند رمي االعتراض ومجموعة الخيارات الثانية وهي ‪When the exception‬‬ ‫‪ is not handled‬والتي تمكننا من تحديد كيف سيتم التصرف عند رمي االعتراض غير المعالج وذلك‬ ‫إما باستمرار التنفيذ أو بمقاطعة التنفيذ للتنقيح وفي معظم الحاالت تكون اإلعدادات االفتراضية مناسبة‪.)"‪"try block reached.)"‪"general catch block reached.)"‪Console.catch.‬‬ ‫}‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪222 -‬‬ ‫‪-‬‬ .throw‬‬ ‫وإذا رمينا االعتراضات بهذه الطريقة فإننا لن نتمكن من معالجتها ضمن بنية ‪ try.finally‬في التابع )(‪ ThrowException‬كما يلي‪:‬‬ ‫‪try‬‬ ‫‪//line33‬‬ ‫{‬ ‫‪Console..catch.WriteLine("ThrowException(\"index\")called.)"‪ThrowException("index‬‬ ‫‪//line38‬‬ ‫}‬ ‫‪catch‬‬ ‫‪//line40‬‬ ‫{‬ ‫‪Console.‬‬ ‫.‬‬ ‫.WriteLine("ThrowException(\"nested index\")" +‬‬ ‫..WriteLine("ThrowException(\"nested index\")" +‬‬ ‫.finally‬إال‬ ‫أنه يمكننا ذلك بواسطة الشيفرة الرئيسية لكن تذكر أن شيفرة كتلة ‪ finally‬ضمن البنية المعششة ستنفذ‪.WriteLine("ThrowException(\"nested index\")" +‬‬ ‫.‪throw‬‬ ‫}‬ ‫‪finally‬‬ ‫{‬ ‫‪Console.‫تصنف االعتراضات ضمن هذه النافذة وفقا لنوعها وفضاء أسماء مكتبة ‪ .‬‬ ‫على سبيل المثال إذا غيرنا الكتلة ‪ try.)"‪"finally block reached..‬‬ ‫.‬‬ ‫الحظ أن علينا توفير كتل ‪ catch‬خاصة دائما ألنواع محددة من االعتراضات بدال من استخدام كتلة‬ ‫‪ catch‬العامة فغذا حصل خطأ ما دون معالجته فغن هذا سيسبب في إخفاق التطبيق عن االستمرار بالتنفيذ‪.‬‬ ‫الحظ أيضا أن بإمكاننا رمي االعتراضات ضمن كتل ‪ catch‬أيضا إما باستخدام الطرق التي تعلمناها‬ ‫مسبقا أو بمجرد كتابة ‪.NET‬ويمكننا أن نرى‬ ‫االعتراضات الموجودة في فضاء األسماء ‪ System‬بتوسعة البند ‪Common Language Runtime‬‬ ‫‪ Exceptions‬ومن ثم اختيار البند ‪ System‬عندئذ ستعرض الئحة من االعتراضات تتضمن االعتراض‬ ‫‪ IndexOutOfException‬الذي استخدمناه مسبقا‪..

‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪223 -‬‬ ‫‪-‬‬ .IndexOutOfRangeException‬قد تم اصطياده ‪.caught‬‬ ‫مصطلح جديد‪:‬‬ ‫رمي ‪ thrown‬واصطياد ‪ caught‬يمث ل المصطلح ‪ thrown‬حدث حصول اعتراض ما أما‬ ‫‪ caught‬فيمثل حدث معالجة هذا االعتراض‪. ‫عندئذ سيستمر التنفيذ في بادئ األمر للكتلة ‪ finally‬هنا ثم مع الكتلة ‪ catch‬المطابقة الموجودة في‬ ‫التابع )(‪ Main‬والشكل التالي يبين تغير النص المطبوع على الخرج‪:‬‬ ‫الشكل (‪)7-24‬‬ ‫نالحظ في هذه الشاشة أن هناك بعض األسطر اإلضافية في الخرج ناتجة من التابع )(‪ Main‬وذلك ألن‬ ‫االعتراض ‪ System.

‬‬ ‫معالجة االعتراضات باستخدام البنية ‪.‬‬ ‫إعداد‪ :‬املهندس حسام الدين الرز‬ ‫‪224 -‬‬ ‫‪-‬‬ .‬‬ ‫لقد تناولنا في هذا الفصل‪:‬‬ ‫استخدام األمر )(‪ Debug.try.Output‬‬ ‫نمط المقاطعة وكيفية الدخول فيه وما يتضمن ذلك من استخدام لنقاط المقاطعة‪. ‫الخالصة‪:‬‬ ‫‪Summary:‬‬ ‫لقد ركزنا في هذا الفصل على التقنيات التي يمكنك استخدامها لتنقيح تطبيقاتك هناك العديد من التقنيات‬ ‫التي تحدثنا عنها في هذا الفصل قد تحتاج إلى استخدام معظمها في نوع من التطبيقات التي ستقوم ببنائها‬ ‫وليس تطبيقات ‪ Console‬فقط‪..catch.WriteLine‬و)(‪ Trace.finally‬‬ ‫لقد غطينا حتى اآلن كل شيء نحتاجه إلنشاء تطبيقات ‪ Console‬بسيطة باإلضافة إلى كيفية تنقيح هذه‬ ‫التطبيقات ومعالجة االعتراضات الحاصلة فيها سوف نتعرف في الجزء التالي من هذا الكتاب على تقنية‬ ‫البرمجة كائنية التوجه القوية‪.Visual Studio 2013‬‬ ‫الخطو ضمن الشيفرة‪.WriteLine‬لكتابة نصوص في إطار‬ ‫‪..‬‬ ‫إطار معلومات التنقيح في ‪.