Module 5 Methods and Parameters جلسه چهارم
متدها در #Cبرنامه ها از تعدادي كلس تشكيل شده اند كه اين بلوكهاي كد ،به نام متد شناخته مي شوند . به عبارت ديگر متدها اعضاء يك كلس هستند كه يا مقدار مشخص ي را بر م ي گردانن د و ي ا عمل خاصي را انجام مي دهند. م ي توان گف ت ك ه متده ا نوع ي تاب ع و يا subroutineو يا زير برنامه هستند. معروفترين متدي كه تا به حال ديده ايم همان متد Mainمي باشد.
تفاوت متدها در #Cبا توابع يا متدها در Cو ++C در زبانهايي همانند Cو يا ++Cمي توان توابع globalتعريف نمود ولي در #Cاين كار امكانپذير نمي باشد و متده ا حتم ا باي د عضوي از يك كلس باشند.
تعريف يك متد ب ه هنگام تعري ف ي ك مت د در زبان #Cبايد موارد زير را تعيين نمود: نام :نام ي ك مت د نباي د در داخ ل كلس براي يك متغيير ،ثابت ويا يك موجوديت غير متدي به كار رفته باشد. بعد از نام يك متد ليست پارامترهاي متد در داخل يك جفت پرانتز ظاهر مي شود. بعد از پرانتزها بدنه اصلي متد قرار مي گيرد كه حتما بايد در بين يك جفت { } محصور شده باشد.
ساختار كلي يك متد static void MethodName ( ) } method body {
مثال using System; class ExampleClass { static void ExampleMethod( ) { Console.WriteLine("Example method"); } static void Main( ) { Console.WriteLine("Main method"); } }
:فراخواني يك متد using System; class ExampleClass { static void ExampleMethod( ) { Console.WriteLine("Hello, world"); } static void Main( ) { Console.WriteLine("The program is starting"); ExampleMethod( ); Console.WriteLine("The program is ending"); } }
فراخواني يك متد از داخل كلس ديگر: براي آنكه بتوان يك متد را از داخل يك كلس ديگ ر فراخوان ي كرد باي د موارد زير را در نظر گرفت: بايد مشخص نمود كه كدام كلس حاوي متد مورد نظر مي باشد ;) (ClassName.MethodName متدي ك ه قص د فراخوان ي آنرا داري م بايد توسط كلمه كليد publicتعريف شده باشد.
مثال فراخواني يك متد از داخل كلسي ديگر using System; class A } public static void TestMethod( ) } Console.WriteLine("This is TestMethod in class A"); { { class B } static void Main( ) } A.TestMethod( ); { {
نکته :در صورتی که در مثال قبل نام کلس را حذف کنیم کامپایل ر در داخ ل کلس Bبدنبال مت د testmethodمی errorصادر گردد و چون آنرا نم ی یاب د پیام می شود. نکته :در صورتی که عبارت Publicدر تعریف متد حذف شود به هنگام اجرا برنامه پیام خطای زیر صادر می شود:
“A.TestMethod() is inaccessible due to its “protection level
کلمه کلید : private در صورتی که درتعریف متد به جای کلمه کلیدی Publicاز کلم ه privateاستفاده کنیم تنها می توان تابع را در داخل همان کلس فراخوانی نمود. از آنجای ی ک ه پی ش فرض مت د ها private می باش د بنابرای ن دو مثال زیر معادل هستند : ;) (private static void MyMethod ;) (static void MyMethod
عبارت : return در صورتی که در داخل یک متد از عبارت returnاس تفاده کنی م ،بع د از اجراء دستور ، returnبلفاص له اجراء برنام ه ب ه متد فراخواننده باز م ی گردد .و در ص ورتی که در اجراء برنامه دستور returnاجراء نشود اجراء متد تا انتهاء متد ادامه می یابد.
: بلفصلreturn مثال عبارت static void ExampleMethod( ) { Console.WriteLine("Hello"); return; Console.WriteLine("World"); }
دریک عبارت شرطیreturn دستور : static void ExampleMethod( ) } int numBeans; //... Console.WriteLine("Hello"); if (numBeans < 10) return; Console.WriteLine("World"); {
returnبه همراه مقدار بازگشت : در صورتی که نوع بازگشتی تابع به غی ر از نوع voidتعری ف شود دراین صورت از مکانیزم returnمی توان برای بازگرداندن مقدار مورد نظر استفاده کرد.
برای بازگرداندن مقدار از یک تابع باید: تابع باید از نوع مقداری که بر می گرداند تعریف شود. حاوی یک عبارت returnباشد. عبارت returnحاوی مقدار بازگشتی باشد.
: مثال class ExampleReturningValue { static int TwoPlusTwo( ) { int a,b; a = 2; b = 2; return a + b; } static void Main( ) { int x; x = TwoPlusTwo( ); Console.WriteLine(x); } }
متغییر های محلی : ه ر مت د دارای متغیی ر های محل ی می باشد .متغییرهای محلی یک متد تنها در داخل آن متد قابل استفاده می باشند و در خارج آ ن مت د شناخته شده نیس تند .با فراخوان ی ه ر مت د متغییر های محل ی آ ن ایجاد شده و ب ا خاتمه متد متغییر های محلی آن ازبین رفته و بنابراین مقادیر آنها قابل دسترس نمی باشند.
: مثال متغییر های محلی static void MethodWithLocals( ) } int x = 1; // Variable with initial value ulong y; string z; ..... {
متغییر های به اشتراک گذاشته شده :در مثال زیر دو مشکل وجود دارد class CallCounter_Bad { static void Init( ) { int nCount = 0; } static void CountCalls( ) { int nCount; ++nCount; Console.WriteLine("Method called {0} time(s)", nCount); } static void Main( ) { Init( ); CountCalls( ); CountCalls( ); } }
رفع مشکل مثال قبل با استفاده از متغییر کلس طح س های در مثال زی ر متغییری ک ه در کلس تعریف شده بین تمامی متد ها به اشتراک گذاشته : می شود class CallCounter_Good { static int nCount; static void Init( ) { nCount = 0; } static void CountCalls( ) { ++nCount; Console.Write("Method called " + nCount + " time(s)."); } static void Main( ) { Init( ); CountCalls( ); CountCalls( ); } }
تداخل حوزه متغییرها در متدnumitems در مثال زیر:مثال محلی است ولی متغییر متد دومmethod1 .همان متغییر به اشتراک گذاشته شده است class ScopeDemo { static int numItems = 0; static void Method1( ) { int numItems = 42; } static void Method2( ) { numItems = 61; }
}
: تعریف پارامترها : مثال static void MethodWithParameters(int n,string y) } // ... {
مکانیزمهای پاس کردن متغییر ها : پارامترها را به سه روش متفاوت می توان پاس کرد : : By Value این نوع پارامترها را گاهی از نوع in parametersنیز می نامند زیرا از طریق آنها تنها می توان مقادیر را به داخل متد ها منتقل کرد. :By Refrence این نوع پارامترها را نوع in out parametersنیز می نامند زیرا از طریق انها می توان مقادیر را به و از متد ها منتقل کرد. : By Output این پارامتر ها را نوع out parametersنیز می گویند چون از طریق آنها تنها می توان مقادیر را از
:Pass by value . می باشد#C این نوع پارامترها نوع پیش فرض پارامتر متد کامل مجزای از متغییر متد فراخواننده می .باشد static void AddOne(int x) { x++; } static void Main( ) { int k = 6; AddOne(k); Console.WriteLine(k); // Display the value 6, not 7
پارامترهای ارجاعی )Refrence :(Parameters
یک پارامتر ارجاعی یک ارجاع به خانه حافظ ه می باشد .و برخلف پارامترهای مقداری ی ک خان ه جدید حافظ ه را اشغال نمی کنند .و در حقیق ت ب ه خان ه ای از حافظه اشاره می کنن د ک ه متغیی ر مربوط ب ه متد فراخواننده در آن نگهداری می شود.
تعریف متغییر های ارجاعی : تعری ف متغیی ر های ارجاع ی ب ا اس تفاده از کلمه کلیدی refانجام می شود. static void ShowReference(ref int nVar, ref )long nCount } // ... {
مثال : در مت د زی ر از پارامترهای مقداری و ارجاعی استفاده شده است: static void OneRefOneVal(ref int refVar, long )longVar } // ... {
نکته :
در فراخوانی متد حتما باید از متغییر ها استفاده نمود و اس تفاده از ثابته ا س بب تولی د پیام خطا می شوند. به هنگام فراخوانی متد ها حتما نوع متغییر های ذک ر شده در فراخوان ی مت د بای د ب ا نوع پارامتر های مت د همخوان ی داشت ه باشن د و برای متغییر های متناظ ر ب ا پارامترهای ارجاع ی بای د ازکلمه کلید refاستفاده نمود .مثال : ;int x ;long q ;)ShowReference(ref x, ref q
مثال برای پارامترهای ارجاعی : static void AddOne(ref int x) { x++; } static void Main( ) { int k = 6; AddOne(ref k); Console.WriteLine(k); // Display the value 7 }
نکته : قبل از فراخوانی یک متد پارامترهای مقداری حتما باید مقدار دهی شده باشند .به عنوان مثال کد زیر اجراء نخواهد شد: ;int k ;)AddOne(ref k ;)Console.WriteLine(k
: Output Parameters
پارامترهای خروج ی شبی ه پارامترهای ارجاع ی هس تند با این تفاوت که توسط آنها فقط می توان مقادیر را از متد ها خارج نمود و نم ی توان توس ط پارامترهای خروجی مقادیری را به متد فرستاد. درتعری ف و فراخوان ی پارامترهای خروج ی بای د از کلمه کلیدی outاستفاده نمود. بر خلف پارامترهای ارجاعی لزم نیست قبل از فراخوانی متد متغییر های متناظر با پارامتر خروجی را مقدار دهی نمود. متغیی ر نوع خروج ی در داخ ل مت د بای د مقدار ده ی اولیه شود.
: مثال static void OutDemo(out int p) { // ... } : OutDemo فراخوانی متد ;(OutDemo(out n
استفاده از تعداد متغییر پارامترها :
برای تعیین لیست پارامترها باید از کلمه کلیدی Params استفاده نمود. در متد تنها باید یک پارامتر نوع Paramsداشت. پارامتر مربوطه باید در انتهای لیست پارامترها قرار داشته باشد. پارامتر مربوطه به صورت یک آرایه تک بعدی تعریف می شود. از آنجایی که پارامتر نوع Paramsبه صورت یک آرایه می باشد حتما تمام پارامترهای لیست باید از یک نوع باشند.
: مثال static long AddList(params long[ ] v) { long total; long i; for (i = 0, total = 0; i < v. Length; i++) total += v[i]; return total; }
به دو روش می توان لیست متغییر ها را پاس نمود:
به صورت لستی از پارامترها به صورت یک آرایه ) (static void Main { ;long x x = AddList(63,21,84); // List x = AddList(new long[ ]{ 63, 21, 84 }); // Array }
نکته : تغییر پارامترهای لیست تاثیری بر روی متغییر ها ی اصلی نداشته و محدود به د مت ل داخ می باشد.
عوامل انتخاب نوع پارامترها : مکانیزم :به صورت معمول یک متد نباید بر روی متغیی ر های برنامه تغییری ایجاد کند بنابراین نوع پارامتر مقداری مرسوم ترین نوع می باشد. در صورتی که متد باید مقداری بازگرداند از returnاستفاده می شود ولی اگر قرار اس ت چن د مقدار باز گردان د باید پارامترهای نوع ارجاع ی و ی ا خروجی بکاربرد.
سربار گذاری متدها: نام یک متد در یک کلس ،باید متفاوت از نام سایر موجودیتها باشد .ولی چند متد می توانند هم نام باشند .به این تکنیک سربارگذاری Overloading گویند. امضاء متدهای سربارگذاری شده ملک تمایز بین آنها می باشند. ب ا اس تفاده از ای ن تکنی ک ب ه راحت ی می توان قابلیتهای جدی د را ب ه متدی ک ه قبل ک د نویسی کرده ایم اضافه نمود.
: مثال class OverloadingExample { static int Add(int a, int b) { return a + b; } static int Add(int a, int b, int c) { return a + b + c; } static void Main( ) { Console.WriteLine(Add(1,2) + Add(3,4,5));}}
امضاء متد ها : نام متدها ،تعداد پارامترها ،نوع پارامتره ا و نوع Modifierهر پارامتر )از قبیل refو (Outامضاء یک متد را تشکیل می دهند.
: مثال static int LastErrorCode( ) } { static int LastErrorCode(int n) } { static int LastErrorCode(int n, int p) } {
مواردی که بر روی امضاء یک متد تاثیر نمی گذارد: نوع بازگشت ی ،نام پارامتره ا بنابراین دو متد زیر دارای امضاء یکسانی بوده و نمی توانند در یک کلس تعریف شوند: )static int LastErrorCode(int n { } )static string LastErrorCode(int x { }
اس تفاده از متدهای سربارگذاری : شده class GreetDemo { static void Greet( ) { Console.WriteLine("Hello"); } static void GreetUser(string Name) { Console.WriteLine("Hello" + Name); } static void Main( ) { Greet( ); GreetUser("Alex"); } }
class GreetDemo { static void Greet( ) { Console.WriteLine("Hello"); } static void Greet(string Name) { Console.WriteLine("Hello" + Name); } static void Main( ) { Greet( ); Greet("Alex");}}