در قسمت دوازدهم با دستور switch و کلماتکلیدی break و continue آشنا شدید. در این قسمت دستور goto و توضیحات تکمیلی دستور switch بیان میشود. همانطور که در قسمت قبل بیان شد، دستور switch یک متغیر را با چندین مورد مقایسه کرده و آن مورد را که با متغیر مطابقت دارد، انتخاب می کند.
به مثال زیر توجه کنید:
using System; class Example { static void Main() { int i; for (i = 0; i < 10; i++) switch (i) { case 0: Console.WriteLine("i is zero"); break; case 1: Console.WriteLine("i is one"); break; case 2: Console.WriteLine("i is two"); break; case 3: Console.WriteLine("i is three"); break; case 4: Console.WriteLine("i is four"); break; default: Console.WriteLine("i is five or more"); break; } } }
خروجی:
همانطور که میبینید، هربار از طریق حلقه مقدار i به ساختار switch داده شده و case مربوط به آن اجرا میشود. هنگامیکه مقدار i بیشتر از ۴ است دیگر در هر بار فقط default اجرا میشود زیرا case مربوط به آن موجود نیست. شما میتوانید هر interger type ای را توسط ساختار switch کنترل کنید، از جمله کاراکتر. به مثال زیر توجه کنید:
using System; class Example { static void Main() { char ch; for (ch = 'A'; ch <= 'E'; ch++) { switch (ch) { case 'A': Console.WriteLine("ch is A"); break; case 'B': Console.WriteLine("ch is B"); break; case 'C': Console.WriteLine("ch is C"); break; case 'D': Console.WriteLine("ch is D"); break; case 'E': Console.WriteLine("ch is E"); break; } } } }
خروجی:
ch is A
ch is B
ch is C
ch is D
ch is E
همانطور که میبینید در این مثال از default استفاده نشده چراکه این بخش از ساختار switch اختیاری است.
در سیشارپ قانونی به اسم no fall-through وجود دارد. طبق این قانون، کامپایلر بعد از statement sequence هر case به سراغ case بعدی نمیرود، چراکه این امر برای زبان سیشارپ یک خطا محسوب میشود و به همین دلیل است که در پایان هر case از break استفاده میکنیم تا کامپایلر بهکلی از ساختار switch خارج شود و به ادامهی برنامه و خطکدها بپردازد. قسمت default نیز نباید fall-through باشد و باید توسط break پایان یابد (از روشهای دیگر نیز میتوان قانون no fall-through را رعایت کرد مانند استفاده از goto بهجای break که در ادامهی این مقاله به شرح آن میپردازیم).
شما همچنین میتوانید چندین case داشته باشید که همگی یک statement sequence دارند:
// Empty cases can fall through. using System; class Example { static void Main() { int i; for (i = 1; i < 5; i++) switch (i) { case 1: case 2: case 3: Console.WriteLine("i is 1, 2 or 3"); break; case 4: Console.WriteLine("i is 4"); break; } } }
خروجی:
i is 1, 2 or 3
i is 1, 2 or 3
i is 1, 2 or 3
i is 4
در این مثال، اگر i شامل مقادیر ۱، ۲ و ۳ باشد اولین ()WriteLine اجرا شده و اگر i برابر با ۴ باشد آنگاه دومین ()WriteLine اجرا میشود.
The goto
goto یک jump statement غیر شرطی است. هنگامیکه برنامه به این کلمه میرسد، به مکان مشخصی از کد که توسط goto مشخص شده است، پرش میکند. goto سالها قبل از چشم برنامهنویسان افتاد چراکه موجب میشد کدنویسی شما مانند اسپاگتی شود! اگرچه هیچ موقعیت برنامهنویسی بهوجود نمیآید که به goto نیاز داشته باشید و در واقع سیشارپ برای اینکه یک زبان کامل باشد به goto نیاز ندارد اما هنوز هم بهندرت (و در برخی موارد بهصورت مفید) استفاده میشود. با این تفاصیر، اگر از goto بهصورت هوشمندانه استفاده شود میتواند سودمند باشد. نگرانی اصلی برنامهنویسان این است که استفاده زیاد از goto باعث شود برنامه ناخوانا و بههم ریخته شود اما در برخی از موارد برعکس است و بهجای بههم ریختگی باعث واضحتر شدن کد خواهد شد. در هرحال استفاده از این دستور پیشنهاد نمیشود مگر بهصورت هوشمندانه و بهجا. goto برای انجام عملیات نیاز به یک label دارد. label یکی از شناسههای سیشارپ است که بعد از آن علامت دونقطه (:) قرار میگیرد. label باید در همان بلاک و متدی باشد که goto قرار دارد (توضیح متد را در مقالات بعدی دنبال کنید). بهعنوان مثال، برنامه زیر یک حلقه است که اعداد ۱ تا ۲۰ را توسط goto و label نمایش میدهد:
using System; class Example { static void Main() { int x = 1; Loop1: // this is label if (x < 20) { Console.WriteLine(x); x++; goto Loop1; // it goes to the Loop1 label } Console.WriteLine("Done!"); } }
goto همچنین میتواند در یک ساختار switch به case و default دلخواه پرش کند. در این مورد، case و default نقش label را بازی میکنند بنابراین میتوانند هدف goto قرار گیرند. نکته اینجاست که goto باید درون switch مربوطه باشد و شما نمیتوانید از بیرون به درون یک switch پرش کنید.
به مثال زیر که از goto در ساختار switch استفاده میکند توجه کنید:
// Use goto with a switch. using System; class Example { static void Main() { for (int i = 1; i < 5; i++) { switch (i) { case 1: Console.WriteLine("In case 1"); goto case 3; case 2: Console.WriteLine("In case 2"); goto case 1; case 3: Console.WriteLine("In case 3"); goto default; default: Console.WriteLine("In default"); break; } Console.WriteLine(); } // goto case 1; // Error! Can't jump into a switch. } }
خروجی:
در این مثال ساختار switch درون یک حلقهی for قرار دارد و در هر دور حلقه، مقدار i به ساختار switch داده میشود. توجه کنید که در ساختار switch چگونه goto به case های مختلف و default پرش میکند. نکتهی دیگر اینجاست که case ها با break پایان نیافتهاند (بهجز default) چراکه استفاده از break در اینجا بیمورد و بیتاثیر است زیرا هر case توسط goto به case دیگری فرستاده شده و نهایتاً در قسمت default از ساختار switch خارج میشود. همانطور که گفته شد، نمیتوانید از بیرون به درون ساختار switch پرش کنید و اگر علامت کامنت را از ابتدای آخرین خطکد برنامه حذف کنید، برنامه کامپایل نمیشود. استفاده از goto در ساختار switch در برخی موارد خاص میتواند مفید باشد اما پیشنهاد نمیشود.
یکی از استفادههای مفید goto میتواند برای خارج شدن از حلقههای تودرتو با تو رفتگی زیاد باشد.
به این مثال دقت کنید:
// Demonstrate the goto. using System; class Example { static void Main() { int i = 0, j = 0, k = 0; for (i = 0; i < 10; i++) { for (j = 0; j < 10; j++) { for (k = 0; k < 10; k++) { Console.WriteLine("i, j, k: " + i + " " + j + " " + k); if (k == 3) goto stop; } } } stop: Console.WriteLine("Stopped! i, j, k: " + i + ", " + j + " " + k); } }
خروجی:
حذف goto در این مثال موجب میشود برای خاج شدن از سه حلقه که تودرتو هستند، از سه if و break استفاده کنید. در این مثال استفاده از goto کد را سادهتر میکند. هرچند که این یک مثال ساختگی است، اما میتوانید موقعیتهایی را بهوجود آورید که استفاده از goto مفید واقع شود. آخرین نکته این است که شما میتوانید توسط goto به خارج از یک بلاک پرش کنید اما نمیتوانید به درون یک بلاک پرش کنید.
شاید در فهم این مثال کمی با مشکل برخورده باشید ولی جای نگرانی نیست، چراکه توضیحات کافی در مورد حلقههای تودرتو خواهد داده شد و مثالها و تمرینات جالبی را انجام خواهیم داد.
salah kurdetani
4 November 2012
سلام استاد . .
من هر سیزده زنگو دانلود کردم و میخوام آفلاین روشون کار کنم و خواستم بگم چرا تمرین خیلی کم دادید ؟؟
کاش میشد تمرینا زیاد باشن روشون کار کنیم .. و مشکلاتو باهاتون حل کنیم .
با تشکر
مسعود درویشیان
5 November 2012
سلام. فعلاً مباحثی که مطرح شده بیشتر خوندنی هستن و نمیشه تمرین آنچنانی باهاشون انجام داد. جلوتر که بریم تمرینهای بیشتر، جالبتر و بهتری خواهیم داشت.
مرسی از همراهیتون
موفق باشید
salah kurdetani
4 November 2012
راستی استاد پیشنهاد کنید تو وب تارگت سی پلاس پلاس هم بزارن ، خدایش خوب میشه !!
پیکسل
5 November 2012
جالب بود اولین باره وب سایت شما رو میبینم ممنونم
داوود
5 November 2012
سلام آقا مسعود؛ ممنون از ارائه آموزشهای خوبتون و بهتون خسته نباشید میگم.
واقعا کار سختی رو برعهده گرفتید.
انشاءالله موفق باشید.
مسعود درویشیان
5 November 2012
سلام، قربان شما داوود جان…
خوانندههای عزیزی مثل شما سختی کار رو از تن آدم بیرون میبرن
amin
7 November 2012
دنبال یه همچین سایتی بودم که بشه سی شارپ و تمرین کنم مرسی چون همه 13 قسمتو دانلود کردمو میخام از امروز شروع کنم
مسعود درویشیان
7 November 2012
Happy coding
فرشید
7 November 2012
با سلام سوالی دارم که مربوط به dllاست معذرت میخوام که اینجا مطرح میکنم ولی اگر ممکنه خیلی فوری به جوابش احتیاج دارم فردا امتحان دارم
من یک پروژه class libraryایجاد کردم و متد ی نوشتم که ده براب عددی را برگردونه تا پایان ;return n*10 نوشتم وبعد f5 را زدم تا dll را تولید کنه و به رفرنس اضافه کنم ولی dllدر debug ایجاد نمیشه میدونید چرا ؟
مسعود درویشیان
8 November 2012
F6 رو بزنید تا Build Solution انجام بشه
f1
13 November 2012
سلام
ببخشيد ميشه در باره مراحل ابتداييش هم كمي مطلب قرار بدين
مانند
void
public
main()
class
ارث بري
كپسول سازي
چند ريختي
مثال عملي باشه ممنونم
مسعود درویشیان
14 November 2012
سلام، در مورد همه اینها بحث خیلی خیلی مفصلی خواهیم داشت و کاملاً با شیگرایی آشنا میشید.
مثالها و تمرینهای زیادی هم انجام میدیم
خیلی عجله نکنید، میرسیم
f1
14 November 2012
salam bebakhshi
darbareh tarahi algoritm ham age mish matalebi ro garar bedin mamnon misham
مهدی
16 November 2012
الانه که هنگ کنم
دستتون درد نکنه علی بود
بهار
5 February 2013
سلام
من امروز سایتتون رو دیدم خیلی عالی بود ممنون از زحماتتون
ولی برای من چون یه خورده کار کردم ساده بود
اگه میشه درمورد مبحث linq صحبت کنید اگه امکانش هست به ایمیلم بفرستید من خودم فیلم آموزشی دارم به زبان اصلیه و زیاد سر در نیاوردم ممنون میشم اگه کمکم کنید
مسعود درویشیان
5 February 2013
سلام. در مورد LINQ توی مقالات آینده زنگ سیشارپ صحبت میکنیم.
Nima
23 February 2013
سلام استاد خیلی جذاب بود مطالب و آموزنده ممنون. . .یا علی !
edris
11 April 2013
با سلام و خسته نباشید،
استاد ما یکم دیر رسیدیم.میخواستم بپرسم که ادامه دارد یا درس ۱۳ آخرین درس بود،
با سپاس
مسعود درویشیان
11 April 2013
سلام، تا الان 28 قسمت منتشر شده، فردا هم قسمت 29 منتشر میشه!!!
ممنون میشم یه نگاه به صفحهی اصلی سایت بندازید :)
علیرضا اسکندرپور شوفری
19 April 2013
زیر تصویر دوم عبارت interger type غلط املایی داره. به integer type اصلاح کنید.
afsaneh
28 April 2013
با سلام
و تشکر فراوان از آموزش #c .
لطفا ادامه بدهید
(*در مورد return توضیح دهید)
مسعود درویشیان
28 April 2013
سلام. ممنون. توی قسمت متدها در مورد return هم توضیح داده شده
T.b
26 September 2013
خیلی ممنون از اموزش جامعی که قرار دادید. اولین بار هست که این وب سایت رو می بینم و حتما مطالب اتی رو دنبال خواهم کرد.
رضا
10 December 2013
جناب درویشان من یه تمرین در حد آموزشهای همین فصل خودم به خودم دادم که خوشحال می شم اگه شما بررسیش کنید.
برنامه رو با موفقیت نوشتم (البته به سختی).
اما دوست دارم بدونم از نظر شما روش فکر کردن من در رابطه با طرح کلی کار و در وهله ی دوم از نظر استفاده ی به جا یا نا به جا از مصالحی که در اختیار داریم چیه !
آیا بهتر بود طور دیگه ای می نوشتم ؟
هدف نوشتن برنامه ای بود که اعداد اول رو به ترتیب چاپ کنه.
پیشاپیش ممنونم.
using System;
class اعداداول
{
static void Main()
{
int x = 1;
loop_1:
if (x < 100) // بزرگترین عدد برای بررسی
{
for (int i = 2; i < x; i++)
{
if (x % i == 0)
{
++x; /* در اینجا چون حاصل تقسیم عدد مورد نظر بر یکی ازاعداد کوچکتر
* از خودش باقیمانده نداشته نتیجه میگیریم که این یک عدد اول نیست
بنابراین این عدد را رها کرده به سراغ عدد بعدی میرویم*/
goto loop_1;
}
continue; /*
اگر باقیمانده داشته باشیم یعنی ممکن است
ایکس عدد اول باشد بنابراین باید
آن را بر سایر اعداد کوچکتر از خودش هم تقسیم کنیم
در نتیجه ایکس را با همان مقدار مجددا به شرط حلقه میفرستیم */
}
Console.WriteLine("adade avval" + " " + x);/* فقط ایکسهایی به اینجا میرسند که به تمامی اعداد کوچکتر از خودشان
* تقسیم شده اند بدون آنکه هرگز باقیمانده ای داشته باشند
پس این ایکس ها اعداد اول هستند که پس از چاپ
یک واحد افزایش یافته و دوباره مورد بررسی قرارمی گیرند */
++x;
goto loop_1;
}
}
}
رضا
10 December 2013
دوستان لطفا راهنمایی کنید چطوری کد رو بزارم که اینطور به هم نریزه
ممنون.
مسعود درویشیان
10 December 2013
کدهاتون رو بین اینها قرار بدین:
مسعود درویشیان
10 December 2013
خوبه ولی بهتر بود بهجای goto از حلقه استفاده میکردید.
رضا
10 December 2013
خیلی ممنون از جوابتون
روش کار می کنم
علی
23 May 2014
ممنونم از آموزش های عالییییییتون
میشه همشو یه کتاب کنین و چاپش کنین…
راستی توی توضیح : The Go to
کلمه ی “تفاسیر” رو اشتباها نوشتید “تفاصیر”
بازم شرمنده
ممنونم
فاطمه
15 October 2014
با سلامی د.واره و خسته نباشید به شما استاد گرامی
واقعا از زحماتتون نهایت تشکر رو دارم ممنون
محمدرضا
21 April 2015
داداش دمت گرم آموزش دستور for بذار گیر کردم