آموزش گام به گام #C (جلسه پنجم: متدها)
1397/12/26 11:30 , میلاد صاحب نظر

آموزش گام به گام #C (جلسه پنجم: متدها)

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

جلسه اول: آغاز کار با #C جلسه ششم: namespaceها جلسه یازدهم: اندیس گذار یا indexerها جلسه شانزدهم: استفاده از اتریبیوت‌ها جلسه بیست و یکم: متدهای بی‌نام یا anonymous
جلسه دوم: عملگرها، نوع‌ها و متغیرها جلسه هفتم: مقدمه‌ای بر کلاس‌های #C جلسه دوازدهم: ساختار یا structها جلسه هفدهم: enumها جلسه بیست و دوم: موضوعاتی در مورد نوع در #C
جلسه سوم: عبارات کنترلی - گزینشی جلسه هشتم: وراثت کلاس در #C جلسه سیزدهم: واسط یا interfaceها جلسه هجدهم: عملگرهای overloading جلسه بیست و سوم: کار با نوع‌های nullable
جلسه چهارم: عبارات کنترلی - حلقه‌ها جلسه نهم: چند ریختی جلسه چهاردهم: مقدمه‌ای بر delegateها و رویدادها جلسه نوزدهم: کپسوله‌سازی  
جلسه پنجم: متدها جلسه دهم: ویژگی یا propertyها جلسه پانزدهم: مقدمه‌ای بر کنترل خطا یا exception جلسه بیستم: مقدمه‌ای بر generic collectionها  

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

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

  • درک ساختار یک متد.
  • درک تفاوت بین متدهای static و instance.
  • آموزش نمونه‌سازی اشیاء.
  • آموزش نحوه فراخوانی متدها از یک شیء نمونه‌سازی شده.
  • درک ۴ نوع از پارامترها.
  • آموزش نحوه استفاده از رفرنس this.

ساختار متد

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

قابلیت ارسال پارامترها و بازگشت مقادیر اجباری نیستند و بستگی به این دارند که شما قصد دارید متد چه کاری انجام دهد. در زیر نمونه‌ای از syntax مورد نیاز برای ایجاد یک متد را مشاهده می‌کنید:

attributes modifiers return-type method-name(parameters )
        {
        statements
        }

مبحث اتریبیوت‌ها و دسترسی‌ها را به جلسات بعدی موکول می‌کنیم. Return-type می‌توانید هر نوع از #C باشد. می‌توان آن را به یک متغیر اختصاص داد تا بعدا در برنامه از آن استفاده کنیم. نام

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

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

لیست ۱-۵، یک متد ساده: OneMethod.cs

using System;

class OneMethod
{
    public static void Main()
    {
        string myChoice;

        OneMethod om = new OneMethod();

        do
       {
            myChoice = om.getChoice();

            // تصمیم‌گیری بر اساس انتخاب کاربر
            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 
            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;

        // A چاپ منوی
        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): ");

        // به دست آوردن انتخاب کاربر
        myChoice = Console.ReadLine();
        Console.WriteLine();

        return myChoice; 
    }
}

برنامه لیست ۱-۵ مشابه برنامه DoLoop از جلسه چهارم است، به استثنای یک تفاوت. به جای نمایش منو و پذیرفتن ورودی در متد ()Main، این عملکرد به یک متد جدید به نام ()getChoice منتقل شده است. نوع بازگشتی(return type) یک رشته است. این رشته در عبارت Switch در متد ()Main به کار رفته است.

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

درون بلوک متد، ابتدا متغیر myChoice را تعریف کرده‌ایم. اگرچه این متغیر هم نام و هم نوع متغیر myChoice در متد ()Main است، اما هر دو متغیرهای منحصر به فردی هستند. آن‌ها متغیرهای local هستند و فقط در همان بلوکی که تعریف شده‌اند قابل دیدن و استفاده هستند.

به عبارت دیگر، متغیر myChoice در متد ()getChoice اصلا از وجود متغیر myChoice در متد ()Main باخبر نیست، و برعکس.

متد ()getChoice یک منو در کنسول نمایش می‌دهد و ورودی کاربر را می‌گیرد. عبارت return داده را از متغیر myChoice به سمت فرا خواننده‌ای که در متد ()Main قرار دارد، بازمی‌گرداند. توجه کنید نوعی که توسط عبارت return بازگشته است، باید مشابه نوع بازگشتی تعریف شده در ابتدای برنامه باشد. در این مثال، این نوع، یک رشته است.

در متد ()Main قبل از اینکه بتوانیم از ()getChoice استفاده کنیم، باید یک شیء OneMethod جدید نمونه‌سازی کنیم. این امر به خاطر نحوه تعریف شدن ()getChoice است. چون هیچ سطح دسترسی static تعیین نکردیم(همانند آنچه در متد ()Main انجام دادیم)، پس متد ()getChoice  تبدیل به یک متد instance می‌شود.

تفاوت بین متدهای instance و متدهای Static این است که می‌توان در متدهای instance، چندین نمونه از یک کلاس ایجاد کرد(یا نمونه‌سازی کرد) و هر نمونه، دارای متد ()getChoice مجزای مخصوص به خودش است.

به هر حال، وقتی یک متد static باشد، هیچ نمونه‌ای از آن متد درونش قرار ندارد و می‌توانید فقط همان یک تعریف موجود از متد static را فراخوانی کنید.

بنابراین، همان‌طور که گفته شد، متد ()getChoice از نوع static نیست و در نتیجه، باید با استفاده از آن یک شیء جدید نمونه‌سازی کنیم. این کار با کد معرفی ()OneMethod om = new OneMethod انجام می‌شود. در سمت چپ تعریف، om قرار دارد که به عنوان رفرنس شیء از نوع OneMethod در نظر گرفته می‌شود.

شناسایی om به عنوان یک رفرنس بسیار مهم است. Om یک شیء نیست، اما یک متغیر است که می‌تواند به سمت یک شیء از نوع OneMethod ارجاع دهد(یا اشاره کند). در سمت راست تعریف، عمل اختصاص یک شیء OneMethod جدید به رفرنس om قرار دارد.

کلیدواژه new یک عملگر #C است که در پشته، یک نمونه جدید از یک شیء ایجاد می‌کند. اتفاقی که در اینجا می‌افتد این است که، یک نمونه OneMethod جدید در پشته ایجاد می‌شود و سپس به رفرنس om اختصاص می‌یابد.

حالا که یک نمونه از کلاس OneMethod داریم که توسط om ارجاع داده می‌شود، می‌توانیم از طریق رفرنس om روی آن نمونه کار کنیم.

متدها، فیلدها و دیگر اعضای کلاس از طریق عملگر “.”(نقطه) قابل دسترسی، قابل شناسایی و قابل دست‌کاری هستند. چون ما می‌خواهیم متد ()getChoice را فراخوانی کنیم، این کار را با استفاده از عملگر نقطه و از طریق رفرنس om انجام می‌دهیم.

یعنی با استفاده از دستور ()om.getChoice. سپس برنامه کدهای درون بلوک ()getChoice را اجرا کرده و مقدار را بازمی‌گرداند. برای گرفتن مقداری که متد ()getChoice بازمی‌گرداند، از عملگر “=”(اختصاص) استفاده می‌کنیم. رشته بازگردانده شده در متغیر محلی myChoice از متد ()Main قرار می‌گیرد.

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

لیست  ۲-۵، پارامترهای متد: 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
       {
            // نمایش منو و گرفتن ورودی از کاربر
            myChoice = mp.getChoice();

            // تصمیم‌گیری برا اساس انتخاب کاربر
            mp.makeDecision(myChoice);

            //کردن برای اینکه کاربر بتواند نتیجه را ببیند Pause
            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;

        // A چاپ منوی
        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): ");

        // به دست آوردن انتخاب کاربر
        myChoice = Console.ReadLine();

        return myChoice; 
    }

    // تصمیم‌گیری
    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;
        }
    }

    // وارد کردن یک آدرس
    void addAddress(ref Address addr)
    {
        Console.WriteLine("Name: {0}, Address: {1} added.", addr.name, addr.address); 
    }

    // حذف یک آدرس
    void deleteAddress(string name)
    {
        Console.WriteLine("You wish to delete {0}'s address.", name); 
    }

    // تغییر یک آدرس
    void modifyAddress(out Address addr)
    {
        //Console.WriteLine("Name: {0}.", addr.name); // !ارور می‌دهد
        addr = new Address();
        addr.name = "Joe";
        addr.address = "C# Station";
    }

    // نشان دادن آدرس‌ها
    void viewAddresses(params string[] names)
    {
        foreach (string name in names)
        {
            Console.WriteLine("Name: {0}", name);
        }
    }
}

لیست ۲-۵، اصلاح‌ شده لیست ۱-۵ است. این کد، برنامه را مدولار(انعطاف پذیر)می‌کند و کدهای بیشتری در آن به کار رفته است تا بتوانیم نحوه انتقال پارامتر را نمایش دهیم.

۴ نوع پارامتر وجود دارند که یک متد #C می‌تواند آن‌ها را کنترل کند: out، ref، params و value. برای تسهیل نمایش کاربر پارامترها، ما یک کلاس Address با دو فیلد رشته ایجاد کردیم.

در متد ()Main ما متد ()getChoice را فراخوانی کردیم تا ورودی کاربر را بگیریم و آن رشته را در متغیر myChoice قرار دادیم. سپس از متغیر myChoice به عنوان یک آرگومان در متد ()makeDecision استفاده کردیم. در کد ()makeDecision متوجه می‌شوید که پارامتر آن به عنوان یک رشته با نام myChoice تعریف شده است.

دوباره یادآوری می‌کنیم، این یک متغیر myChoice جدید است و با آرگومان به کار رفته در فراخوانندِ فرق می‌کند و در این متد از نوع local‌یا محلی است. چون پارامتر myChoice از متد makeDecision هیچ تعیین سطح دیگری ندارد، به عنوان یک پارامتر value در نظر گرفته می‌شود. مقدار واقعی آرگومان روی پشته کپی شده است.

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

عبارت switch در متد ()makeDecision برای هر case یک متد فراخوانی می‌کند. این فراخوانی‌های متد با آن‌هایی که در متد ()Main استفاده می‌کردیم، فرق دارند. به جای استفاده از رفرنس mp، آن‌ها از کلیدواژه this استفاده می‌کنند. This یک ارجاع دهنده به شیء فعلی شما است.

می‌دانیم که شیء فعلی نمونه‌سازی شده است، چون متد ()makeDecision یک متد static نیست. در نتیجه، درون یک نمونه مشابه، می‌توانیم از رفرنس this برای فراخوانی متدها استفاده کنیم.

متد ()addAddress یک پارامتر ref می‌گیرد. این بدان معنا است که یک رفرنس به یک پارامتر، درون متد کپی شده است.

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

همان‌طور که می‌دانید، متدها دارای مقادیر بازگشتی هستند، اما گاهی لازم است بیش از یک مقدار را از یک متد بازگردانید. یک پارامتر out به شما اجازه می‌دهد مقادیر بیشتری از یک متد بازگردانید.

متد ()modifyAddress دارای یک پارامتر out است. پارامترهای out فقط به تابع فراخوانندِ بازگشت می‌دهند. به خاطر وجود قوانین اختصاص قطعی و صریح، تا زمانی که یک مقدار قابل‌قبول به این متغیر اختصاص داده نشود، نمی‌توانید از آن استفاده کنید.

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

پیش از اینکه متد شما مقدار بازگرداند، باید یک مقدار به پارامتر out اختصاص دهید.

یکی از ویژگی‌های خیلی مفید افزوده شده به زبان #C، پارامتر params است. این پارامتر به شما اجازه می‌دهد متدی تعریف کنید که بتواند تعداد متغیری از آرگومان‌ها را بپذیرد. پارامتر params باید یک آرایه تک بعدی یا ناهموار باشد. وقتی متد ()viewAddress فراخوانی می‌شود، ما ۴ آرگومان رشته را منتقل می‌کنیم.

تعداد آرگومان‌ها متغیر است و به طور خودکار به یک []string تبدیل می‌شود. در متد ()viewAddress ما از یک حلقه for each برای نمایش هر کدام از این رشته‌ها استفاده می‌کنیم.

به جای لیست آرگومان‌های از نوع رشته، ورودی می‌تواند همچنین یک آرایه از رشته‌ها باشد. پارامتر params به عنوان یک پارامتر فقط ورودی در نظر گرفته شده است و هر تغییری فقط بر کپی محلی آن اثر می‌گذارد.

خلاصه

شما ساختار یک متد را درک کردید. ۴ نوع از پارامترها عبارت‌اند از value، ref، out و params. وقتی می‌خواهید از یک متد instance استفاده کند، باید شیء آن متد را نمونه‌سازی کنید، در مقابل آن متدهای Static قرار دارند که می‌توانید هر موقع خواستید خود آن‌ها را فراخوانی کنید.

رفرنس this به شیء نگه دارنده‌اش اشاره می‌کند و می‌توان از آن برای اشاره به اعضای شیء نگه دارنده‌اش نیز استفاده کرد(به خصوص متدها).

منبع: C# - Station

جلسه بعد                                                                جلسه قبل

 مطالب مرتبط

 مقدمه ای بر زبان برنامه نویسی #C و پلتفرم NET Framework.
7 دلیل منطقی برای آموختن #C
 طبقه بندی زبان های برنامه نویسی
به دست آوردن Exceptionها در #C و یافتن همه خطاها
 LINQ(زبان جستجوی یکپارچه)
برنامه نویسی شیءگرا چیست؟

از آخرین دوره های آموزشی و تخفیف ها مطلع شوید

با تکمیل فرم زیر ، از اخبار و اطلاعات به روز برنامه نویسی و تکنولوژی عقب نمانید

آخرین مطالب

آموزش جامع SQL Server (جلسه ۱۲)
آموزش جامع SQL Server (جلسه ۱۲)

دستور UPDATE در SQL Server برای تغییر داده‌های موجود در یک جدول، از دستور UPDATE به شکل زیر استفاده ...

آموزش جامع SQL Server (جلسه ۱۵)
آموزش جامع SQL Server (جلسه ۱۵)

دستور DROP TABLE در SQL Server گاهی، لازم است یک جدول که دیگر استفاده‌ای ندارد را حذف کنید. برای ...

آموزش جامع SQL Server (جلسه ۳۵: Window Functionها – بخش ۲)
آموزش جامع SQL Server (جلسه ۳۵: Window Functionها – بخش ۲)

بخش اول از آخرین مبحث دوره جامع آموزش SQL Server در جلسه قبلی بررسی شد. این مبحث که ...

آخرین دیدگاه ها

دیدگاه خود را درباره این پست بنویسید

فرم ارسال نظرات