مشخصات مقاله
-
1513
-
0.0
-
2333
-
0
-
0
آموزش متدها در CSharp
کلیه حقوق مادی و معنوی این مقاله متعلق به آموزشگاه تحلیل داده می باشد و هر گونه استفاده غیر قانونی از آن پیگرد قانونی دارد.
متدها
می توان به کمک متدها کد را به ماژول هایی تقسیم کرد که هریک وظیفه ی معلومی را انجام می دهند.
اهداف این مبحث
آشنایی با ساختار متد
آموزش تفاوت بین متدهای static (ایستا) و instance(نمونه)
آموزش نمونه سازی (instantiate) شی ها (objects)
آموزش نحوه ی فراخوانی متدهای شی نمونه سازی شده
آشنایی با چهار نوع پارامتر
آموزش شیوه ی استفاده از ارجاع (reference) this
ساختار متدها
متدها از آن جایی که به کاربر اجازه می دهند منطق (logic) را به واحدهای متمایز تقسیم کند بسیار کارامد هستند. می توان اطلاعات به متد ارسال کرد، به وسیله آن یک یا چند دستور اجرا کرد و با کمک آن مقدار بازگشتی (return value) را بازیابی کرد. البته قابلیت بازگرداندن مقدارها و ارسال پارامتر اختیاری است و به آنچه از متد انتظار دارید برای شما انجام دهد بستگی دارد. دستور نحوی که برای ساخت متد به آن نیاز پیدا می کنید به صورت زیر می باشد.
attributes modifiers return-type method-name(parameters )
{
statements
}
نوع بازگشتی (return-type) می تواند هر نوع C# باشد. می توان برای استفاده از آن درآینده، نوع بازگشتی را به متغیر اختصاص داد. اسم متد (method name) شناسه ی منحصر به فردی برای آنچه مایلید method بنامید می باشد. برای اینکه فهم کد بهبود یابد، اسم متد نه تنها باید معنا دارباشد بلکه بهتر است با وظیفه (task) ای که متد قرار است انجام دهد مرتبط باشد. پارامترها به شما اجازه می دهند هم اطلاعات به متد بفرستید هم داده از آن دریافت کنید. پارامترها داخل پرانتز قرار می گیرند.دستورهای داخل {} قابلیت (functionality) متد را اجرا می کنند.
Listing 5-1. یک متد ساده : OneMethod.cs
using System;
class OneMethod
{
public static void Main()
{
string myChoice;
OneMethod om = new OneMethod();
do
{
myChoice = om.getChoice();
// Make a decision based on the user's choice
switch (myChoice)
{
case "A":
case "a":
Console.WriteLine("You wish to add an address.");
break;
case "D":
case "d":
Console.WriteLine("You wish to delete an address.");
break;
case "M":
case "m":
Console.WriteLine("You wish to modify an address.");
break;
case "V":
case "v":
Console.WriteLine("You wish to view the address list.");
break;
case "Q":
case "q":
Console.WriteLine("Bye.");
break;
default:
Console.WriteLine("{0} is not a valid choice",myChoice);
break;
}
// Pause to allow the user to see the results
Console.WriteLine();
Console.Write("press Enter key to continue...");
Console.ReadLine();
Console.WriteLine();
} while (myChoice != "Q" && myChoice != "q"); // Keep going until the user wants to quit
}
string getChoice()
{
string myChoice;
// Print A Menu
Console.WriteLine("My Address Book\n");
Console.WriteLine("A - Add New Address");
Console.WriteLine("D - Delete Address");
Console.WriteLine("M - Modify Address");
Console.WriteLine("V - View Addresses");
Console.WriteLine("Q - Quit\n");
Console.Write("Choice (A،D،M،V،or Q): ");
// Retrieve the user's choice
myChoice = Console.ReadLine();
Console.WriteLine();
return myChoice;
}
}
برنامه ی Listing 5-1 شبیه برنامه DoLoop است، با این تفاوت که به جای پرینت کردن فهرست و پذیرفتن داده از main method، این قابلیت را به متد جدیدی به نام getChoice() واگذار می کند. نوع بازگشتی یک string (رشته) است. Stringدر دستور switch در Main() به کاربرده شده. اسم متد "getChoice" اتفاقی را که هنگام فراخوانی آن رخ می دهد را توصیف می کند. به دلیل اینکه پرانتزها تهی هستند، هیچ داده ای به متد "getChoice" فرستاده نمی شود.
ابتدا متغیر myChoice را در بلوک متد (method block) معرفی می کنیم. اگر چه با متغیر myChoice در Main() هم نوع و هم اسم است، هر یک از این دو متغیر منحصر به فرد بوده و کاملا از هم متمایز هستند.به این خاطر که این متغیرها محلی هستند، آن ها را می توان فقط در بلوک هایی که در آن تعریف شده اند مشاهده کرد.به عبارت دیگر، myChoice موجود در "getChoice" هیچ آگاهی نسبت به موجودیت myChoice در Main() ندارد و عکس این قضیه نیز صادق است.
getChoice فهرست گزینشی برای کنسول پرینت کرده و ورودی کاربر را دریافت می کند. دستور return داده را از متغیر myChoice به فراخواننده Main() که متعلق به getChoice است بازمی گرداند. در نظر داشته باشید که نوع بازگردانده شده توسط دستور return (بازگشت) باید با نوع- بازگشتی (return-type) متعلق به تعریف تابع (function declaration) یکی باشد که در این مثال یک string (رشته) است.
قبل از اینکه بتوانیم از getChoice استفاده کنیم، باید در متد Main() یک شی OneMethod نمونه سازی کنیم. این به خاطر نحوه ای است که getChoice() با آن تعریف شده. چون که مُدیفایر (پیراینده/modifier) static (ایستا) برای Main() تعریف نشده، getChoice به متد نمونه (instance method) تبدیل می شود. تفاوت بین instance method و static method در این است که در متد نمونه چند نمونه از یک کلاس می توانند به وجود آیند و هر نمونه (instance) برای خود متد getChoice جداگانه پیدا می کند. اما در متد ایستا (static method)، هیچ نمونه ای از آن متد وجود ندارد و تنها می توان همان یک تعریف متد static را فراخواند.
همان گونه که ذکر شد، getChoice() ایستا نیست و برای به کارگیری آن باید یک شی جدید نمونه سازی شود. این امر به وسیله ی OneMethod om = new OneMethod() قابل اجرا است. در سمت چپ تعریف (declaration) ارجاع شی om قرار دارد که از نوع onemethod می باشد. این حقیقت که om یک ارجاع است از اهمییت بالایی برخوردار است. خود یک شی نیست، اما متغیری است که می تواند به شی (متعلق به) نوع onemethod اشاره کند. در سمت راست تعریف، جاگزینی شی جدید onemethod به جای ارجاع om را مشاهده می کنید.کلیدواژه ی new در واقع یک عملگر C# است که روی هیپ (heap) نمونه ی جدیدی از شی پدید می آورد. آنچه در اینجا اتفاق می افتد، خلق یک نمونه ی onemethod جدید در هیپ و اختصاص آن به ارجاع om است. حال، نمونه ای از کلاس onemethod در دست داریم که om به آن اشاره می کند و دست ما برای دستکاری نمونه از طریق ارجاع om باز است.
برای دسترسی،شناسایی و دستکاری متدها،فیلدها و دیگر اعضای کلاس می توان از عملگر "." استفاده کرد.برای بازخوانی getChoice()، از عملگر نقطه سرتاسر ارجاع om استفاده می شود به این شکل : om.getChoice() . سپس برنامه دستورها را در بلوک getChoice() اجرا می کند و عملیات return را انجام می دهد. به منظور ظبط مقداری که getChoice() بازمی گرداند، از عملگر جایگزینی/assignment "=" استفاده می کنیم. string بازگردانده شده در متغیر محلی myChoice متعلق به Main() گنجانده می شود.
Lisitng 5-2. پارامترهای متد : MethodParams.cs
using System;
class Address
{
public string name;
public string address;
}
class MethodParams
{
public static void Main()
{
string myChoice;
MethodParams mp = new MethodParams();
do
{
// show menu and get input from user
myChoice = mp.getChoice();
// Make a decision based on the user's choice
mp.makeDecision(myChoice);
// Pause to allow the user to see the results
Console.Write("press Enter key to continue...");
Console.ReadLine();
Console.WriteLine();
} while (myChoice != "Q" && myChoice != "q"); // Keep going until the user wants to quit
}
// show menu and get user's choice
string getChoice()
{
string myChoice;
// Print A Menu
Console.WriteLine("My Address Book\n");
Console.WriteLine("A - Add New Address");
Console.WriteLine("D - Delete Address");
Console.WriteLine("M - Modify Address");
Console.WriteLine("V - View Addresses");
Console.WriteLine("Q - Quit\n");
Console.WriteLine("Choice (A،D،M،V،or Q): ");
// Retrieve the user's choice
myChoice = Console.ReadLine();
return myChoice;
}
// make decision
void makeDecision(string myChoice)
{
Address addr = new Address();
switch (myChoice)
{
case "A":
case "a":
addr.name = "Joe";
addr.address = "C# Station";
this.addAddress(ref addr);
break;
case "D":
case "d":
addr.name = "Robert";
this.deleteAddress(addr.name);
break;
case "M":
case "m":
addr.name = "Matt";
this.modifyAddress(out addr);
Console.WriteLine("Name is now {0}.", addr.name);
break;
case "V":
case "v":
this.viewAddresses("Cheryl", "Joe", "Matt", "Robert");
break;
case "Q":
case "q":
Console.WriteLine("Bye.");
break;
default:
Console.WriteLine("{0} is not a valid choice", myChoice);
break;
}
}
// insert an address
void addAddress(ref Address addr)
{
Console.WriteLine("Name: {0}، Address: {1} added.", addr.name, addr.address);
}
// remove an address
void deleteAddress(string name)
{
Console.WriteLine("You wish to delete {0}'s address."، name);
}
// change an address
void modifyAddress(out Address addr)
{
//Console.WriteLine("Name: {0}."، addr.name); // causes error!
addr = new Address();
addr.name = "Joe";
addr.address = "C# Station";
}
// show addresses
void viewAddresses(params string[] names)
{
foreach (string name in names)
{
Console.WriteLine("Name: {0}"، name);
}
}
}
listing5-2 نسخه ی اصلاح شده listing 5-1 است که برای نمایش بهتر ارسال پارامتر پیاده سازی بیش تری در آن گنجانده. C# با چهار نوع پارامتر کار می کند که عبارتند از :out، ref، params و value. برای روشن سازی کاربرد پارامترها یک Address class به همراه دو string field به وجود آورده ایم. در Main() برای دریافت ورودی کاربر و قرار دادن string در متغیر myChoice باید getChoice() را فراخواند. سپس برای فعال سازی makeDecision() از myChoice به عنوان آرگومان استفاده می کنیم. در تعریف makeDecision() متوجه می شوید که تنها پارامترش با نام myChoice به عنوان string معرفی شده است. بازهم، این myChoice ای جدید، جدا از فراخواننده ی آرگومان (caller’s argument) و محلیِ این متد است. چون که پارامتر myChoice متعلق به makeDecision() هیچ مُدیفایر دیگری ندارد، یک value parameter (پارامتر مقدار) حساب می شود.مقدار واقعی آرگومان در پشته کپی می شود.مقدارهایی که value parameter ارائه می دهد، محلی بوده و هر تغییر وارد آمده بر آن متغیر محلی، هیچ تاثیری بر مقدار متغیری که در فراخواننده آرگومان استفاده شده ندارد.
دستور switch در makeDecision() برای هر مورد یک متد فرامی خواند. این فراخوانی متدها با آن هایی که در Main() استفاده کردیم متفاوت هستند. به جای استفاده از ارجاع mp، از کلیدواژه ی this استفاده می کنند. Thisاشاره ای است به شی جاری. ما می دانیم که شی کنونی به خاطر این که makeDecision()، متدی ایستا نیست نمونه سازی شده است. بنابراین، می توان از ارجاع this برای فراخوانی متدها در همان نمونه استفاده کرد.
متد addAddress() به پارامتر ref نیاز دارد. به این معنا که ارجاع به پارامتر در متد کپی می شود.این پارامتر همچنان به همان شی واقع در هیپ اشاره می کند که ارجاع اصلی به کاربرده شده در آرگومان فراخواننده به آن اشاره کرد. این متعاقباً به این معنا است که هر تغییر وارد آمده بر شی ارجاع محلی (local reference’s object)، شی ارجاع فراخواننده (caller reference’s object) را نیز تغییر می دهد.کُد نمی تواند ارجاع را تغییر دهد، اما می تواند شی ای که به آن ارجاع می شود (reference) را تغییر دهد. اینگونه شما پارامتر ورودی/خروجی (input/output parameter) خواهید داشت.
همان طور که مطلع هستید، متدها مقدارهای بازگشتی (return value) دارند، با این وجود شاید نیاز باشد که بیش از یک مقدار از متد بازگردانده شود. پارامتر out به شما اجازه می دهد بیش از یک مقدار از متد برگردانید.
modifyAddress() دارای پارامتر out است. پارامترهای out فقط به تابع های فراخوانی (calling function) بازگردانده می شوند.به دلیل وجود قوانین جایگزینی (assignment) معین، نمی توان این متغیر را تا زمانی که مقدار معتبری به آن اختصاص داده شده به کاربرد. اولین خط درmodifyAddress() به منظور تشریح همین موضوع توضیح داده (comment) شده. آن را uncomment کرده و سپس آن را کامپایل/ترجمه کنید ببینید چه اتفاقی رخ می دهد. پس از اینکه مقدار معتبر اختصاص (assign) داده شد و برنامه آن را بازگرداند (return)، مقدار پارامتر out داخل متغیر آرگومان فراخواننده (caller’s argument variable) قرار داده می شود. اختصاص مقدار به پارامتر out پیش از بازگشت متد الزامی است.
ویژه گی جدید و پرکارامد دیگر زبان C# پارامتر params هست، که به شما اجازه می دهد متدی تعریف کنید که تعداد متنوع و متغیری آرگومان بپذیرد. پارامتر params حتماً باید یا آرایه ی تک بعدی باشد و یا آرایه ی jagged. هنگام فراخوانی viewAddresses()، در واقع چهار آرگومان رشته ای (string argument) به داخل آن ارسال می شود. تعداد آرگومان ها متغیر است و به صورت خودکار به string[] تبدیل می شود. در viewAddresses() برای پرینت هر یک از این strings (رشته ها) از حلقه ی foreach استفاده می شود. به جای فهرست آرگومان های strings (رشته ها)، ورودی همچنان می توانست آرایه ی string باشد. پارامتر params تنها پارامتر ورودی به حساب می آید و هر تغییر وارد آمده ای فقط کپی (نمونه) محلی را تحت تاثیر قرار می دهد.
به طور خلاصه، با ساختار متد آشنا شدیم. چهار نوع پارامترها عبارتند از value، ref، out و params. هنگام استفاده از متد نمونه (instance method)، باید شی آن را نمونه سازی کنید. این امر بر خلاف متد ایستا (static method) می باشد که می توان آن را هر زمان فراخواند. ارجاع this به شی دربردانده (containing object) خود اشاره می کند و می توان از آن برای اشاره به اعضای شی دربردانده از جمله متدها نیز کمک گرفت.