مقدمه‌ای بر برنامه‌نویسی و زبان سی شارپ

image

مارگارت همیلتون از نخستین برنامه‌نویسان جهان، در کنار کدهایی که برای ماموریت آپولو ۱۱ ناسا نوشته شده است؛ کدهایی که انسان را به ماه فرستاد. این کدها به تازگی توسط دختر او در دسترس عموم قرار گرفته و در گیت هاب قابل مشاهده‌اند.

بسیاری از افراد برنامه‌نویسی را به عنوان امری بسیار دشوار می‌دانند؛ چرا که هنگام مواجهه با یک کد کاراکترهایی بی‌معنی را در برابر خود می‌بینند که به نظرشان عجیب‌وغریب و پیچیده بوده و درکشان ممکن نیست.

این اتفاق شاید برای هر برنامه‌نویس خبره‌ای در اولین برخوردش با کدهای نامفهوم نیز افتاده باشد. اما چیزی که اهمیت دارد این است که با تمرین و فهم اصولی ساختار کد این ترس به مرور از بین می‌رود. چون:

این کدها آن‌قدر که در نگاه اول به نظر می‌رسند غیرقابل فهم نیستند.

در این قسمت سعی کرده‌ایم تا نگاه اولیه‌ای به برنامه‌نویسی و مخصوصاً زبان سی شارپ بیندازیم. بعد از حذف شدن یونیتی اسکریپت از لیست زبان‌های پشتیبانی شده توسط یونیتی، زبان سی شارپ یکه‌تاز برنامه‌نویسی یونیتی شده است و بنابراین یادگیری آن بخش جدایی ناپذیری از روند توسعه در یونیتی خواهد بود. سعی شده است که توضیحات داده شده برای یادگیری پیش‌نیازی نداشته باشند.

البته دانستن این نکته خالی از لطف نیست که منبعی برای تبدیل شدن به یک برنامه‌نویس وجود ندارد. پیدا کردن مهارت در برنامه‌نویسی زمان‌بر است و به تمرین زیادی احتیاج دارد. این به معنی دشواری مسیر نیست؛ اما نباید انتظارات عجیب داشت و نباید هم خیلی زود ناامید شد.

عناوین آموزشی مثل «یادگیری برنامه‌نویسی در ۲۱ روز» فریبنده هستند و بیشتر جنبه‌ی تبلیغاتی دارند. یکی از راه‌های یادگیری برنامه‌نویسی در ۲۱ روز در زیر توضیح داده شده است:

image

برنامه‌نویسی بیشتر از آن‌که تایپ کردن کد باشد، یک طرز فکر است. تمام عملیاتی که یک کد انجام می‌دهد ابتدا توسط قوه‌ی حل مسئله‌ی برنامه‌نویس در ذهنش انجام شده است و او در هنگام دست به کیبورد شدن صرفاً در حال نوشتن طرز فکر خود به زبان برنامه‌نویسی است. در واقع برنامه‌نویسی مهارت حل مسئله است و نوشتن کد پیاده‌سازی این حل مسئله است.

مسئله‌ای را تصور کنید که از برنامه‌نویس خواسته تا اعداد اول قبل از x (متغیر) را مشخص کند. حل این مسئله ربط چندانی به برنامه‌نویسی ندارد. برنامه‌نویس برای حل این مسئله ابتدا به این نکته توجه می‌کند که عدد ۱ نه اول است و نه مرکب؛ بنابراین از دور خارج می‌شود. در مرحله‌ی بعد تک تک اعداد را از ۲ تا x-1 بررسی می‌کند که اول هستند یا خیر؛ اگر اول هستند اعلام شوند و در غیر این صورت نادیده گرفته شوند.

این مسئله یک زیرمسئله در درون خود دارد که آن هم باید حل شود؛ چگونه بفهمیم که یک عدد اول است؟ پاسخ این است که آن عدد (مثلاً y) باید تنها دو مقسوم‌علیه (۱ و y) داشته باشد. پس برای بررسی این که یک عدد اول است یا خیر کافی است به ازای هر عدد متغیری به نام n در نظر گرفته و آن را برابر ۰ قرار دهیم. سپس عدد را تقسیم بر اعداد ۱ تا y کنیم و به ازای هر بار که باقیمانده‌ی تقسیم صفر شد، یکی به n اضافه کنیم. در نهایت در صورتی که n=2 بود نتیجه می‌گیریم که y عدد اول است.

این یک روش حل مسئله‌ی فوق است. بدیهی است که بیشمار روش دیگر نیز برای حل این مسئله وجود دارد. حل مسئله به زبان برنامه نویسی ارتباطی ندارد.

انجام عملیاتی خاص به روشی که برنامه‌نویس در ذهن دارد مستقل از زبان برنامه‌نویسی است.

آن‌چه که برنامه‌نویسی را چالش برانگیز می‌کند طرز فکر برنامه‌نویسی است. این طرز فکر توسط شخص و با تمرین و گذر زمان به دست می‌آید و قابل آموزش دادن نیست. اگر فردی این مهارت را داشته باشد، تقریباً تنها با یادگیری قواعد نحوی (syntax) یک زبان برنامه‌نویسی جدید می‌تواند بدون هیچ مشکلی در آن زبان شروع به برنامه‌نویسی کند.

شاید بتوان زبان برنامه‌نویسی را مثل وسیله‌ی نقلیه در نظر گرفت. با هر وسیله‌ی نقلیه‌ای (هواپیما، قطار، اتومبیل شخصی، …) می‌توان به مقصد موردنظر رسید و در این میان تنها کیفیت مسیر است که تفاوت خواهد داشت. سی شارپ به همین دلیل انتخاب شده است. یکی از زبان‌های برنامه‌نویسی نسبتاً جوانی که تحت مالکیت مایکروسافت بوده و بروزرسانی و نگهداری قابل قبولی دارد.

خوشبختانه syntax زبان سی شارپ شباهت زیادی به syntax سایر اعضای خانواده‌ی C از جمله سی پلاس پلاس، جاوا، پی اچ پی، اکما اسکریپت (زبانی که جاوا اسکریپت از آن تکامل یافته است و به مرور جایگزین آن شده است) و… دارد و این بدان معنی است که با یادگیری syntax یکی از این زبان‌ها، می‌توان به سایر زبان‌های خانواده‌ی C تسلطی نسبی یافت و از آن‌جا که زبان ++C در دانشگاه‌های ایران تدریس می‌شود دانشجویان رشته‌های مهندسی می‌توانند از تجربیات خود در این زمینه استفاده کنند.

برنامه‌نویسی تحت کنسول سی شارپ

معمولاً هنگام یادگیری هرکدام از زبان‌های برنامه‌نویسی مفاهیم پایه‌ای آن با استفاده از برنامه‌نویسی تحت کنسول آموزش داده می‌شود. خروجی برنامه‌های تحت کنسول فاقد هرگونه گرافیک و به صورت متن بوده و در محیط کنسول (پنجره‌ای شبیه به Command Prompt) نمایش داده خواهند شد؛ چرا که هدف تنها یادگیری ساختار، قواعد و عملکرد کدی که نوشته شده است می‌باشد و ظاهر مدرن چندان اهمیتی ندارد.

image

کد سی شارپ در سمت چپ و خروجی آن تحت کنسول در سمت راست؛ این کد در Visual Studio Community نوشته و اجرا شده است.

بعد از این مرحله است که افراد مطابق با هدف خود (برای مثال سی شارپ برای بازی‌سازی در یونیتی) کدنویسی را در یک نرم‌افزار تخصصی و کاربردی ادامه می‌دهند.

برای برنامه‌نویسی سی شارپ و اجرای آن تحت کنسول به یک نرم‌افزار IDE سی شارپ احتیاج خواهید داشت.

نکته

روش‌هایی برای اجرای فایل‌های سی شارپ (و زبان‌های دیگر) به صورت مستقیم در Command Prompt ویندوز و Terminal مک و لینوکس وجود دارد؛ اما این روش‌ها هیچ‌وقت کاربرد عملی نخواهند داشت و اجرای یک کد ساده را بسیار طاقت‌فرسا می‌کنند.

IDE رسمی سی شارپ (و مایکروسافت) غول نرم‌افزاری ویژوال استودیو است؛ یکی از گران‌ترین، پیچیده‌ترین و سنگین‌ترین نرم‌افزارهای حال حاضر. نیازی نیست که چنین نرم‌افزاری (که با کامپوننت‌هایش تقریباً ۲۰ گیگابایت حجم دارد) را برای برنامه‌نویسی تحت کنسول سی شارپ بر روی سیستم خود نصب کنید (هرچند که چنین امکانی در آن وجود دارد). مایکروسافت نسخه‌ی سبک‌تر و رایگانی هم تحت عنوان Visual Studio Community ارائه می‌کند. از دیگر IDEهای سی شارپ می‌توان MonoDevelop (که سابقاً یونیتی آن را در فایل نصب خود باندل می‌کرد) و JetBrains Rider را نام برد. انتخاب IDE برای تمرین کدها بیشتر سلیقه‌ای است و کار کردن با آن‌ها و خروجی کنسولشان تقریباً تفاوتی ندارد. ما به دلیل بروز بودن JetBrains Rider و توصیه‌ی یونیتی به استفاده از آن، همچنین برای آشنا شدن کاربران با محیط IDE به جهت استفاده از آن در یونیتی هنگام مهاجرت به یونیتی این IDE را انتخاب کرده‌ایم. بدیهی است که دنبال کردن مباحث با هر IDE دیگری نیز امکان‌پذیر است.

تعریف solution در سی شارپ

solution در سی شارپ به مجموعه‌ای از پروژه‌ها گفته می‌شود که به نوعی با هم ارتباط دارند.

برای مثال یک دانشگاه را در نظر بگیرید. برای سیستم اتوماسیون این دانشگاه باید پروژه‌های مختلفی نوشته شود. پروژه‌ای برای قسمت پرداخت شهریه و صندوق، پروژه‌ای برای قسمت ثبت نمرات، پروژه‌ای برای سلف دانشگاه و پروژه‌های دیگری که برای هر قسمت به صورت جداگانه نوشته می‌شود. با وجود این که این پروژه‌ها از یکدیگر مستقل هستند و ممکن است حتی توسط تیم‌های مختلفی توسعه داده شده باشند، اما بر روی داده‌های مشترکی عملیات انجام می‌دهند.

ساختن solution برای مواردی که تنها یک پروژه وجود دارد نیز اجتناب‌ناپذیر است. این امکان برای موقعی در نظر گرفته شده است که نیاز به ایجاد پروژه‌ی دومی مشترک با منابع پروژه اول به وجود بیاید.

solution چیزی به جز مجموعه‌ای از رفرنس‌ها به پروژه‌های درون خود و تنظیماتشان نیست.

ایجاد یک solution در JetBrains Rider

بعد از باز کردن JetBrains Rider پنجره‌ی خوش‌آمدگویی آن باز می‌شود:

image

برای ساخت یک solution جدید بر روی New Solution کلیک کنید (در صورتی که solutionای از قبل ایجاد کرده باشید ستونی در سمت چپ این پنجره مشاهده می‌شود که لیست آخرین solutionهای ساخته شده را در خود جای داده است).

image

در پنجره‌ی بعدی ابتدا از ستون سمت چپ گزینه‌ی Console Application را انتخاب کرده و سپس نام solution، پروژه و مسیر قرارگیری آن‌ها را به دلخواه مشخص کنید. دقت کنید که Language بر روی #C قرار داشته باشد.

در صورتی که در قسمت Framework با پیغام قرمز رنگ No target frameworks were found on this machine مواجه شدید، به معنی نصب نبودن دات نت فریمورک بر روی سیستم شما است.

دات نت فریمورک شامل ابزارهایی است که توسط مایکروسافت توسعه داده شده و برای اجرای فایل‌های نوشته شده به زبان‌های برنامه‌نویسی مایکروسافت لازم هستند.

پس از نصب دات نت فریمورک بسته به نسخه‌های نصب شده‌ی آن بر روی سیستم، می‌توان نسخه‌ی دلخواه را در این قسمت انتخاب کرد. نسخه‌ی فریمورک نسخه‌ی سی شارپی که با آن برنامه‌نویسی انجام می‌شود را تعیین می‌کند. برای مثال به منظور استفاده از آخرین قابلیت‌های اضافه شده به سی شارپ، باید از سی شارپ نسخه‌ی ۶٫۰ استفاده کنیم که نسخه‌ی دات نت فریمورک آن ۴٫۶ است (در تنظیمات یونیتی نیز می‌توان نسخه‌ی دات نت فریمورک مورد استفاده را تغییر داد).

در نهایت بر روی Create کلیک کنید.

بررسی اجزای زبان سی شارپ

تعریف کلاس، فیلد و متد

این اجزا از ارکان اصلی زبان‌های برنامه‌نویسی شی‌گرا (مثل سی شارپ) هستند که هرکدام تعریف و فلسفه‌ی وجودی نسبتاً مفصلی دارند؛ بنابراین تعاریفی که ادامه گفته می‌شود صرفاً برای آشنایی بسیار مختصر هستند.

کلاس، یک جزء نرم‌افزاری است که دارای فیلدهایی بوده که خصوصیات خود را در آن نگهداری می‌کند و متدهایی که وظایف محول شده به آن کلاس را انجام می‌دهند. به طور معمول، از روی کلاس یک یا چندین شی ایجاد می‌شود.

برای مثال کلاسی به نام «دانشجو» را در نظر بگیرید. دانشجو دارای خصوصیاتی از جمله «نام»، «نام خانوادگی»، «شماره دانشجویی» و… است (فیلدها) و می‌تواند عملیات‌هایی مثل «شارژ کارت تغذیه»، «امتحان دادن»، «فارغ‌التحصیل شدن» و… را انجام دهد (متدها).

بعد از تعریف این کلاس می‌توان از روی آن شی تعریف کرد. سه دانشجوی فرضی به نام‌های اشکان صادقی، مهرداد رئیسی و آرزو آفری را در نظر بگیرید. برای تعریف این دانشجویان به کامپیوتر، سه شی از روی کلاس دانشجو می‌سازیم و فیلدهای هرکدام از این سه شی را با مقادیر مختص خودشان پر می‌کنیم. برای مثال فیلد «نام خانوادگی» شی مربوط به اشکان صادقی (که از روی کلاس دانشجو ساخته شده است) برابر رشته‌ی "صادقی" می‌باشد.

البته در برنامه‌نویسی مقدماتی کنسول از این مفاهیم استفاده نمی‌شود. دلیل static تعریف کردن اجزا (که در ادامه مشاهده خواهید کرد) نیز همین بوده و به مباحث شی‌گرایی مرتبط می‌شود. این مباحث در جای خود توضیح داده خواهند شد.

تا قبل از آشنا شدن با مباحث شی‌گرایی، تمام فیلدها و متدهایی که تعریف می‌کنیم به صورت static و در بدنه‌ی کلاس Program نوشته می‌شوند. این کلاس اصلی پروژه‌های کنسول بوده که متد Main درون آن قرار دارد. شروع اجرای کدهای پروژه‌های تحت کنسول از درون این متد آغاز می‌شود.

ساز و کار اجزای زبان سی شارپ

image

برای اجرای صحیح کد لازم است که این سلسله‌مراتب رعایت شود. به عنوان مثال تعریف متد در خارج از یک کلاس باعث بروز خطا می‌شود.

ساختار یک فایل کد سی شارپ

کدهای سی شارپ در فایل‌هایی با فرمت cs ذخیره می‌شوند. این فایل‌ها را با ویرایشگر متنی ساده نیز می‌توان باز کرد و ویرایش نمود. اما IDE علاوه بر این کار (آن هم خیلی حرفه‌ای‌تر از یک ویرایشگر متنی ساده) عمل کامپایل کد را نیز انجام می‌دهد. کامپایل به معنی تبدیل کدهای نوشته شده توسط برنامه‌نویس به زبان قابل درک برای ماشین و اجرای کد ماشین ساخته شده در سیستم و سرانجام نمایش آن در کنسول می‌باشد.

بعد از ایجاد solution در JetBrains Rider تنها فایل سی شارپ موجود در پروژه به نام Program.cs که به طور پیش‌فرض ایجاد شده است و فایل اصلی پروژه به حساب می‌آید به صورت خودکار باز می‌شود. محتوای این فایل به صورت زیر است (توضیحات بیشتر کد در آن «کامنت» شده است):

//در صورت نیاز به اجزای فضای نام دیگری که در سلوشن موجود است با استفاده از دستور یوزینگ در این قسمت آن را به کد معرفی میکنیم
namespace ConsoleApplication1
{
internal class Program
{
//متد اصلی برنامه
public static void Main(string[] args)
{
//شروع دستورات از این نقطه است
}
}
}

در سطر ۳ نام پروژه به صورت فضای نام (namespace) به solution معرفی شده است. این بدین معنی است که در صورتی که قصد استفاده از اجزای این namespace را در فایل دیگری از پروژه داشته باشیم باید کد زیر را که وظیفه‌ی import کردن فضای نام را دارد در ابتدای فایل مدنظر بنویسیم:

using ConsoleApplication1;

در سطر ۸ متدی با نام Main معرفی شده که در برنامه‌نویسی تحت کنسول سی شارپ نقطه‌ی شروع اجرای کدها از بعد «آکلاد باز }» این متد است (سطر ۱۰).

نوشتن اولین برنامه

بر اساس یک رسم قدیمی، اولین برنامه‌ای که هنگام یادگیری یک زبان برنامه‌نویسی جدید نوشته می‌شود برنامه‌ی ساده‌ای است که عبارت Hello World را چاپ می‌کند. به این منظور دستوری که وظیفه‌ی چاپ در کنسول را بر عهده دارد را درون متد Main می‌نویسیم (سطر 9):

using System;
namespace ConsoleApplication1
{
internal class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}
نکته

در آخر هر دستور سی شارپ باید از کاراکتر «سمی‌کالن ;» استفاده شود. این کاراکتر به کامپایلر (نرم‌افزاری که کد سی شارپ را به زبان ماشین تبدیل می‌کند) اعلان پایان دستور را می‌دهد. استفاده نکردن از این کاراکتر باعث ایجاد خطا می‌شود.

این دستور از کلاس Console استفاده کرده است؛ کلاسی که مدیریت امور مربوط به کنسول (از جمله نوشتن متن در آن) را بر عهده دارد. این کلاس در فضای نام System قرار دارد که توسط مایکروسافت توسعه داده شده است. بنابراین برای استفاده از این دستور ابتدا باید فضای نام آن را در فایل وارد کنیم که این کار با نوشتن دستور using System; در بالای کد (سطر 1) انجام شده است.

اگر پس از معرفی کردن فضای نام شروع به نوشتن دستور اصلی کنید متوجه خواهید شد که بعد از نوشتن چند حرف از کلمه‌ی Console لیستی در زیر آن باز شده و این کلمه را پیشنهاد می‌دهد و پس از تایپ کاراکتر نقطه نیز لیست جدیدی باز شده که اعضای کلاس Console را توصیه می‌کند. می‌توان به جای تایپ کامل یک عبارت بعد از نوشتن تنها چند کاراکتر از آن با کلیدهای بالا و پایین کیبورد در این لیست به جستجو پرداخت و پس از یافتن عبارت مدنظر با زدن کلید enter آن را به کد اضافه کرد. به این قابلیت IntelliSense گفته می‌شود. این یکی از مهم‌ترین قابلیت‌های IDEها می‌باشد.

image

IntelliSense در JetBrains Rider که در حال حدس زدن عبارتی که برنامه‌نویس در ذهن دارد می‌باشد

دلیل این که عبارت Hello World در گیومه نوشته شده این است که این عبارت برای کامپیوتر معنای محاسباتی ندارد و تنها یک انسان می‌تواند آن را درک کند. به همین خاطر آن را در یک بسته‌بندی (گیومه‌ها) قرار می‌دهیم. کامپیوتر تنها می‌تواند این بسته را عیناً تحویل دهد. به عبارت بین دو گیومه رشته (string) گفته می‌شود. در صورتی که در ورودی دستور (بین دو پرانتز) عبارت 2+2 را بنویسیم خروجی آن در کنسول 4 خواهد بود. اما اگر در ورودی دستور عبارت “2+2” را بنویسیم کامپایلر آن را یک رشته‌ی بی‌معنی در نظر گرفته و پردازش ریاضی بر روی آن انجام نمی‌دهد. بنابراین در کنسول عیناً 2+2 نمایش داده خواهد شد. کامپایلر به محتوای درون یک رشته ورود پیدا نمی‌کند (مگر در دستوراتی خاص).

الحاق (concat) رشته

در صورتی که قصد داشته باشیم رشته در کنار یک عبارت با معنی قرار بگیرد (برای مثال به منظور استاده درون یک دستور چاپ کنسول) از عمل الحاق استفاده می‌کنیم. در این عمل با استفاده از کاراکتر «بعلاوه +» دو (یا چند) جزء به هم متصل می‌شوند:

using System;
namespace ConsoleApplication1
{
internal class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Hasele 2+2 mishavad: " + (2 + 2));
}
}
}

در این مثال رشته‌ی "Hasele 2+2 mishavad: " و عبارت با معنی (2 + 2) به وسیله‌ی یک بعلاوه به هم الحاق شده‌اند. مقدار درون رشته تغییری نمی‌کند و 2+2 محاسبه شده و در خروجی به همراه رشته نمایش داده می‌شود. خروجی این کد به صورت زیر است:

Hasele 2+2 mishavad: 4

دلیل استفاده از پرانتز در عبارت (2 + 2) این است که کامپایلر این بعلاوه را به عنوان علامت جمع محاسباتی در نظر بگیرد و نه به نشانه‌ی الحاق.

اجرای کد

برای اجرای کد و مشاهده‌ی برنامه در کنسول، از نوار بالای صفحه بر روی دکمه‌ی Run (با آیکون Play سبزرنگ) کلیک کنید و سپس در پنجره‌ی باز شده گزینه‌ی Run را انتخاب کنید. بعد از چند لحظه در صورت نبود خطا کد کامپایل شده و اجرا می‌شود.

در صورت وجود خطا کامپایلر نوع خطا را توضیح داده و مکان آن (شماره سطر و کاراکتر) را بیان می‌کند. با دوبار کلیک بر روی توضیحات خطا caret (اشاره‌گر چشمک‌زنِ هنگامِ ویرایش متن که مکان تایپ را نشان می‌دهد) به آن مکان از کد منتقل می‌شود.

نکته

کنسول JetBrains Rider برخلاف ویژوال استودیو و MonoDevelop به صورت توکار بوده و در پنجره‌ی جدیدی نمایش داده نخواهد شد. البته این حالت در تنظیمات قابل تغییر است.

نکته

در صورتی که از IDE دیگری استفاده می‌کنید که کنسول را در پنجره‌ی جداگانه‌ای نشان می‌دهد؛ ممکن است بعد از اجرای کد متوجه شوید که پنجره‌ی کنسول باز شده و در کسری از ثانیه بسته می‌شود. این مسئله به این خاطر است که برنامه به سرعت اجرا شده و پس از تکمیل اجرا وظیفه‌ی خود را تمام شده می‌بیند و بسته می‌شود. چرا که وظیفه‌ی برنامه پردازش بوده است و نه نمایش نتایج پردازش. برای جلوگیری از بسته شدن خطا این کد را به عنوان آخرین دستور به متد Main اضافه کنید:

Console.ReadKey();

این دستور در واقع برنامه را در انتظار فشرده شدن یکی از کلیدهای کیبورد توسط کاربر می‌گذارد. اما ما برای جلوگیری از بسته شدن و مشاهده‌ی برنامه از آن استفاده می‌کنیم.

خوانایی کد

هرکس می‌تواند کدی بنویسد که یک کامپیوتر بتواند درک کند؛ برنامه‌نویسان خوب کدی می‌نویسند که انسان‌ها بتوانند درک کنند. (مارتین فولر)

یک کد به توانایی اجرای دستور مدنظر برنامه‌نویسش خلاصه نمی‌شود؛ یک کد تمیز علاوه بر این ویژگی باید خوانایی داشته باشد. خوانایی به معنی آسان بودن درک کد برای سایر برنامه‌نویسانی که آن را مشاهده می‌کنند است. برای خوانا کردن کد از روش‌هایی استفاده می‌شود که در ادامه بررسی می‌کنیم. این روش‌ها تاثیری بر کارکرد کد ندارند.

استفاده از فضای خالی و لاین بریک

همانطور که گفته شد، کامپایلر سی شارپ با رسیدن به سمی‌کالن متوجه پایان یافتن دستور می‌شود. اما در کدهای سی شارپ پس از پایان یک دستور به سطر بعدی رفته و دستور جدید را در آن‌جا می‌نویسیم. نوشتن هر دستور در یک سطر تاثیری در روند کد و اجرای آن نداشته و تنها برای بهتر شدن خوانایی کد توسط انسان طبق این استاندارد عمل می‌کنیم. کامپایلر کاراکتر space (به جز فاصله‌ی میان دو کلمه) و لاین بریک (رفتن به سر سطر بعدی) را نادیده می‌گیرد. برای مثال این کد برنامه‌ی Hello World است که فضاهای خالی و لاین بریک‌هایش حذف شده است:

using System;namespace ConsoleApplication1{internal class Program{public static void Main(string[] args){Console.WriteLine("Hello World!");}}}

برای کامپیوتر این دو کد کوچک‌ترین تفاوتی ندارند اما بدیهی است که خواندن چنین کدی برای انسان بسیار دشوار است.

استفاده از تورفتگی (indent)

کدهای سی شارپ از بلوک‌های مختلفی تشکیل شده‌اند. هرآنچه که میان دو آکلاد باز و بسته قرار می‌گیرد یک بلوک به حساب می‌آید. در سی شارپ به کرات از بلوک‌های تودرتو استفاده می‌شود که نشانگر سلسله‌مراتب اجزا نسبت به همدیگر می‌باشد. برای نشان دادن این سلسله‌مراتب از تو رفتگی در کد استفاده می‌کنیم.

using System;
namespace ConsoleApplication1
{
internal class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}

کد برنامه‌ی Hello World بدون تورفتگی

همین کد با تورفتگی به صورت زیر است:

using System;
namespace ConsoleApplication1
{
internal class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
}

ملاحضه می‌شود که وجود تورفتگی تا چه حد تشخیص اجزای کد و سلسله‌مراتب آن‌ها را آسان‌تر می‌کند. معمولاً IDEها به طور معمول این تورفتگی‌ها را ایجاد می‌کنند. برای ایجاد تورفتگی به صورت دستی کافی است به ازای هر مرحله تو رفتگی یک بار کلید tab فشرده شود.

کامنت‌گذاری

هنگامی که قصد داریم برای قسمت‌های مختلف کد توضیحاتی بنویسیم از کامنت استفاده می‌شود. کامنت‌های یک کد متن‌هایی هستند که تنها برای خوانده شدن توسط انسان نوشته می‌شوند و کامپایلر آن‌ها را نادیده می‌گیرد. استفاده از کامنت در دو حالت بیشتر است؛ حالت اول زمانی است که برنامه‌نویس بعد از پایان یک پروژه و گذشت زمان طرز کار قسمت‌هایی از کدهایی که نوشته است را فراموش می‌کند. برای جلوگیری از این اتفاق و به منظور یادآوری خودِ برنامه‌نویس او در بالای بخش‌های مهم کد، توضیح کوتاهی از نحوه‌ی عملکرد آن را می‌نویسد تا هنگام برخورد مجدد با کد مشکلی به وجود نیاید.

حالت دوم هنگامی است که یک تیم به صورت گروهی در حال توسعه است و یا یک برنامه‌نویس قصد استفاده از کدهای برنامه‌نویس دیگری را دارد. در این حالت برنامه‌نویس اصلی کد خود را کامنت‌گذاری می‌کند تا افراد دیگر طرز کار کد را متوجه شوند.

در زبان سی شارپ به دو صورت می‌توان کامنت‌گذاری کرد.

  • کامنت یک سطری: در صورت نوشتن دو کاراکتر «اسلش /» در کنار هم، کامپایلر از ابتدای اسلش اول تا آخر سطر را کامنت فرض کرده و نادیده می‌گیرد:
using System;
namespace ConsoleApplication1
{
internal class Program
{
public static void Main(string[] args)
{
Console.WriteLine(2 + 3 + 4); //The result will be 9
}
}
}
  • کامنت چند سطری: در صورت تایپ یک کاراکتر اسلش و سپس کاراکتر ستاره، کامپایلر از ابتدای اسلش را تا جایی که مدنظر داشته باشیم به صورت کامنت در نظر می‌گیرد. برای اعلان پایان منطقه‌ی کامنت از توالی کاراکتر ستاره و اسلش (برعکس حالت شروع) استفاده می‌کنیم. اسلش دوم آخرین کاراکتری است که در این حالت کامنت می‌شود:
using System;
namespace ConsoleApplication1
{
internal class Program
{
public static void Main(string[] args)
{
Console.WriteLine(2 + 3 + 4);
}
}
}
/* This code is written in C sharp,
* Copyleft - 2020
* Unitycorn.ir
*/

در کامنت‌گذاری چند سطری برای زیبایی بیشتر در ابتدای هر سطر کامنت از توالی کاراکتر فاصله و ستاره استفاده می‌شود. انجام این عمل اختیاری است.

کامنت‌ها علاوه بر نوشتن توضیح کاربرد دیگری هم دارند. فرض کنید در یک کد نیاز داشته باشیم که قسمتی از آن اجرا نشود (به دلایلی مثل تست کردن کد بدون فعال بودن یک قابلیت). در این حالت نیازی نیست که آن قسمت را حذف کنیم؛ بلکه به سادگی آن را به صورت کامنت در می‌آوریم. در این حالت کامپایلر آن را به عنوان متن می‌شناسد و نادیده‌اش می‌گیرد. به این عمل کامنت اوت کردن می‌گویند:

using System;
namespace ConsoleApplication1
{
internal class Program
{
public static void Main(string[] args)
{
Console.WriteLine("What color is the sky?");
//Console.WriteLine("Answer: Blue");
}
}
}

متغیر

متغیر فضایی خالی در حافظه است که قبل از اجرای برنامه و یا حین آن می‌تواند از انواع مختلفی از داده (عدد صحیح، عدد اعشاری، کاراکتر، رشته و…) اشغال شده و پس از آن محتوای درونش درخواست و فراخوانی شود. برای مثال وقتی که یک برنامه عددی را دریافت می‌کند آن را در متغیر قرار می‌دهد.

متغیر یکی از اصلی‌ترین ارکان برنامه‌نویسی است. در زبان‌های شی‌گرا مثل سی شارپ، در صورتی که متغیر هم‌رده‌ی متدهای کلاس تعریف شود به آن فیلد و صورت تعریف آن درون متد به آن متغیر محلی می‌گویند. متغیر محلی صرفا درون بلوک متد قابل دسترسی است.

تعریف متغیر در برنامه

برای تعریف یک متغیر از الگوی DataType variableName = value; استفاده می‌کنیم.

به عنوان مثال: int playerLives = 5;

در این‌جا متغیری به نام playerLives ایجاد کردیم که می‌تواند اعداد صحیح (نوع داده int) را در خود ذخیره کند.

به صورت قراردادی نام متغیرها به صورت camelCase نوشته می‌شود (یعنی در عبارتی که قصد داریم آن را نام متغیر بگذاریم فاصله‌های بین کلمات را حذف کرده و حرف اول کلمات دوم به بعد را به صورت بزرگ می‌نویسیم مانند justToShowYouWhatIAmTalkingAbout).

آرایه

آرایه نوعی ساختمان داده است که می‌تواند به جای یک مقدار، چندین مقدار از نوع داده‌ی مدنظر ما بپذیرد (متغیر چندخانه‌ای). هر خانه‌ی این آرایه شماره‌ای دارد که از طریق آن می‌توان به محتوایش دسترسی پیدا کرد. این شماره‌گذاری از 0 آغاز می‌شود؛ بنابراین شماره‌ی خانه‌ی nام n-1 می‌باشد.

image

نحوه‌ی تعریف آرایه

در نهایت برای خواندن خانه‌ی موردنظر (در این مثال خانه‌ی چهارم) از دستوری مشابه زیر استفاده می‌کنیم:

Console.WriteLine(a[3]);

دقت کنید که از 4 یک عدد کم کردیم (به دلیل شروع شماره‌گذاری از صفر).

انواع داده (DataType)

در کامپیوتر داده انواع مختلفی دارد. هنگام تعریف یک متغیر باید نوع داده‌ای که اجازه دارد در آن قرار بگیرد را نیز مشخص کرد. بنابراین به بررسی تعدادی از مهم‌ترین انواع داده می‌پردازیم:

  • نوع داده‌ی int: متغیری که با این نوع داده تعریف شود تنها می‌تواند اعداد صحیح را در خود جای بدهد (در صورت قرار دادن عدد اعشاری در متغیر قسمت اعشاری حذف می‌شود). البته ظرفیت این نوع داده محدود است اما اعداد معمولی با کاربرد روزمره را می‌تواند نگهداری کند.

  • نوع داده‌ی float: متغیری که با این نوع داده تعریف شود می‌تواند عدد اعشاری تا حداکثر 7 رقم اعشار را در خود جای بدهد.

  • نوع داده‌ی double: این نوع داده مشابه float بوده اما دقت آن تا حداکثر 15 رقم اعشار است.

  • نوع داده‌ی bool: متغیری که با این نوع داده تعریف شود تنها می‌تواند یکی از دو حالت صحیح یا غلط را در خود جای دهد. مانند یک لامپ که تنها می‌تواند روشن یا خاموش باشد. از این متغیر اغلب برای تصمیم‌گیری در برنامه‌نویسی بسته به محتوای این متغیر استفاده می‌شود.

برای مثال سوال «آیا امروز جمعه است؟» را در نظر بگیرید. این سوال تنها می‌تواند یکی از جواب‌های بله یا خیر را داشته باشد. بعد از پاسخ به این سوال است که می‌توان براساس آن عملی (مثل سر کار رفتن) را انجام داد.

عملگرها

عملگر به یک یا دو کاراکتر متوالی گفته می‌شود که برحسب قرارداد در دستور عملیاتی مرتبط با ریاضی و منطق انجام می‌دهند.

image

در این جدول a یک متغیر از نوع int در نظر گرفته شده و x و y عبارت‌های منطقی هستند.

نکته

برای درک بهتر تفاوت a++ و ++a این کد را بررسی کنید:

using System;
namespace ConsoleApplication1
{
internal class Program
{
//In this code, we want to figure out the difference between a++ and ++a operations
public static void Main(string[] args)
{
int a;
//Let's assign a an arbitrary value, for example 10
a = 10;
//Now let's try a++ operation on it
Console.WriteLine("In this case, at first the value will be printed in the cosole, then it will increase; look: " + a++);
Console.WriteLine("After a++ operation, the value of a is: " + a);
//Let's reassign 10 to a once more to try ++a as well
a = 10;
//Now let's try the ++a operation
Console.WriteLine("In this case, at first the value will increase, then it will be printed in the cosole; look: " + ++a);
Console.WriteLine("After ++a operation, the value of a is: " + a);
}
}
}//Unitycorn.ir

دستورات و statementهای مهم سی شارپ

image

دقت کنید که شرط درون حلقه‌ها حتماً باید در جایی از برنامه نقض شود؛ در غیر این صورت یک حلقه‌ی نامتناهی به وجود می‌آید که اجرای آن متوقف نشده و باعث هنگ و کرش کردن برنامه می‌شود.

نکته

در صورتی که در بلوک شرط یا حلقه تنها یک دستور وجود دارد می‌توان از نوشتن آکلادها صرفنظر کرد. هرچند که نوشتن آن‌ها برای تمیزی کد (و همچنین احتمال اضافه کردن دستورات بیشتر به بلوک در آینده) پیشنهاد می‌شود.

نکته

با استفاده از دستور break; در هر نقطه از حلقه (و یا سایر بلوک‌ها) می‌توان از آن خارج شد.

متد (تابع)

متد دستگاهی است که در ریاضی و زبان‌های غیرشی‌گرا تابع نامیده می‌شود. این دستگاه داده‌ی ورودی را دریافت کرده، بر روی آن عملیات و پردازش انجام داده و نتیجه‌ی کارش را تحت عنوان خروجی باز می‌گرداند.

image

برای مثال در ریاضی تابع f(x)=x^2 عددی را دریافت کرده (ورودی)، آن را به توان 2 می‌رساند (پردازش) و نتیجه (خروجی) را باز می‌گرداند. در برنامه‌نویسی نیز دقیقاً با همین مفهوم روبرو هستیم.

تابع صفر، یک یا چند آرگومان (ورودی) دریافت کرده که عمل پردازش را بر روی آن‌ها انجام می‌دهد و نتیجه (خروجی) با دستور return بازگردانده می‌شود. اگر تعداد آرگومان‌ها بیشتر از یک عدد باشد آن‌ها را با کامای انگلیسی از هم جدا می‌کنیم.

البته باید بدانیم که یک متد تنها به خروجی‌اش خلاصه نشده و کدهای داخل یک متد مثل هر کد دیگری اجرا می‌شوند. برای مثال در صورتی که در یک متد دستوری مبنی بر چاپ در کنسول داشته باشیم هنگام فراخوانی آن متد و ورودی دادن به آن، دستور چاپ کنسول نیز اجرا خواهد شد. به همین دلیل می‌توان متدهایی بدون خروجی نیز نوشت. هنگام نوشتن این متدها به جای نوشتن نوع خروجی از کلمه‌ی void (پوچ) استفاده می‌شود. مانند متد Main؛ چرا که این متد وظیفه‌ی اجرای برنامه‌ی کنسول را برعهده دارد و مهم کدهایی هستند که در آن نوشته می‌شوند تا خروجی آن.

به صورت قراردادی نام متدها (و کلاس‌ها) به صورت PascalCase نوشته می‌شود (یعنی در عبارتی که قصد داریم آن را نام متد بگذاریم فاصله‌های بین کلمات را حذف کرده و حرف اول کلمات را به صورت بزرگ می‌نویسیم مانند JustToShowYouWhatIAmTalkingAbout).

برای استفاده از متدی که تعریف کرده‌ایم، در محل موردنظر نام آن را نوشته و داخل پرانتز مقابل آن، پارامتر(های) مدنظر خود را می‌نویسیم. برای وارد کردن چندین پارامتر (ورودی) از کامای انگلیسی استفاده می‌شود. دقت کنید که ترتیب ورود پارامترها اهمیت دارد.

برنامه‌ی زیر را درنظر بگیرید:

using System;
namespace ConsoleApplication1
{
internal class Program
{
public static void Main(string[] args)
{
bool gender;
Console.WriteLine("Welcome to our store. Please enter your name:");
string name = Console.ReadLine();
Console.WriteLine("Are you a man? (yes for being a man, any other text for being a woman)");
string genderAnswer = Console.ReadLine();
gender = genderAnswer.Equals("yes") ? true : false;
Console.WriteLine(
SayHello(name, gender)
);
}
public static string SayHello(string customerName, bool isCustomerAMan)
{
return "Hello " + (isCustomerAMan ? "Mr. " : "Mrs. ") + customerName;
}
}
}//Unitycorn.ir

در این برنامه متدی به نام SayHello قرار دارد (سطر 24) که یک ورودی از نوع string به نام customerName (نام مشتری) و یک ورودی دیگر از نوع بولی به نام isCustomerAMan (آیا مشتری یک مرد است؟) دریافت می‌کند. سپس بسته به پارامترهای دریافتی رشته‌ی «سلام آقای/خانم [نام مشتری]» را بازگردانی می‌کند (سطر 26). سپس در بدنه‌ی متد isCustomerAMan (سطر 20) متد فراخوانی شده و مقادیر موردنظر در آن پاس (وارد) می‌شوند.

نکته

در سطرهای 17 و 26 از قابلیتی به نام ternary operator استفاده شده است که شکلی کوتاه شده از ساختار if/else معمولی می‌باشد.