درخواست های ارتباط
جستجو
لیست دوستان من
صندوق پیام
همه را دیدم
  • در حال دریافت لیست پیام ها
صندوق پیام
رویدادها
همه را دیدم
  • در حال دریافت لیست رویدادها
همه رویدادهای من
تخفیف های وب سایت
همه تخفیف ها

عضویت در

کانال تلگرام

توسینسو

اطلاعات مطلب
مدرس/نویسنده
حسین احمدی
امتیاز: 215942
رتبه:3
344
265
416
2833
حسین احمدی ، بنیانگذار TOSINSO ، توسعه دهنده وب و برنامه نویس ، بیش از 12 سال سابقه فعالیت حرفه ای در سطح کلان ، مشاور ، مدیر پروژه و مدرس نهادهای مالی و اعتباری ، تخصص در پلتفرم دات نت و زبان سی شارپ ، طراحی و توسعه وب ، امنیت نرم افزار ، تحلیل سیستم های اطلاعاتی و داده کاوی ... پروفایل کاربر

آموزش زبان سی شارپ - قسمت دهم :: آشنایی با متدها در زبان سی شارپ (بخش دوم)

تاریخ 49 ماه قبل
نظرات 5
بازدیدها 6000
در قسمت قبلی سری آموزش سی شارپ در مورد نحوه تعریف و استفاده از متدها صحبت کردیم. در ادامه مبحث متدها را ادامه داده و با برخی از ویژگی های مربوط به متدها آشنا خواهیم شد. مواردی که در این قسمت مورد بررسی قرار خواهند گرفت عبارتند از:

  1. آشنایی با کلمات کلیدی ref و out
  2. استفاده از آرایه به عنوان ورودی و خروجی متد
  3. آشنایی با کلمه کلیدی params
  4. قابلیت method overloading و کاربرد آن
  5. نوشتن توابع بازگشتی


کلمات کلیدی out و ref


در قسمت قبل در مورد پارامترها در متدها صحبت کردیم. پارامترها مقادیری هستند که به یک متد ارسال می شوند. دو کلمه کلیدی ref و out در زبان سی شارپ وجود دارند که نوع رفتار با یک پارامتر را تغییر می دهند. ابتدا با یک مثال ساده شروع می کنیم. کد زیر را در نظر بگیرید:

private static void Main(string[] args)
{
    var number = 8;
    Console.WriteLine(number);
    Do(number);
    Console.WriteLine(number);
}

public static void Do(int num)
{
    num = 12;
}

متغیری با نام number تعریف کردیم و مقدار آن را برابر 8 قرار دادیم. سپس این متغیر را در خروجی چاپ کرده و هنگام فراخوانی متد Do متغیر number را به آن ارسال کردیم. در داخل متد Do مقدار پارامتر را به 12 تغییر دادیم و مجدد مقدار number را در خروجی چاپ کردیم. اگر خروجی برنامه را مشاهده کنید، دو بار عدد 8 در خروجی چاپ خواهد شد. دلیل آن، ارسال مقدار به پارامتر متد می باشد. زمانی که ما برای مقدار یک پارامتر از یک متغیر تعریف شده استفاده می کنیم، مانند مثال بالا، مقدار متغیر داخل پارامتر متد کپی می شود و در صورت تغییر دادن مقدار پارامتر، متغیر ما تغییری نخواهد کرد. اما می توان این رفتار را تغییر داد. کلمه کلیدی ref هنگام تعریف پارامتر، می گوید به جای کپی کردن مقدار متغیر داخل پارامتر، از آدرس متغیر تعریف شده برای پارامتر استفاده کن. یعنی، آدرس متغیر تعریف شده به پارامتر تخصیص داده شده و پارامتر و متغیر، هر دو به یک خانه حافظه اشاره می کنند. در این شرایط، با تغییر مقدار پارامتر، مقدار متغیر نیز تغییر خواهد کرد. هنگام تعریف پارامتر کافیست قبل از نوع پارامتر کلمه کلیدی ref را بنویسیم. کد بالا ره به صورت زیر تغییر می دهیم:

private static void Main(string[] args)
{
    var number = 8;
    Console.WriteLine(number);
    Do(ref number);
    Console.WriteLine(number);
}

public static void Do(ref int num)
{
    num = 12;
}

در صورتی که کد بالا را مجدد اجرا کنیم، ابتدا عدد 8 و پس از فراخوانی متد، عدد 12 در خروجی چاپ می شود، زیرا پارامتر num در متد Do را از نوع ref تعریف کردیم. دقت کنید که هنگام فراخوانی متد، باید قبل از نام متغیر کلمه کلیدی ref نوشته شود، در غیر این صورت برنامه کامپایل نشده و پیغام خطا دریافت خواهید کرد. نکته بعدی که باید به آن توجه کنید، زمانی که از کلمه کلیدی ref استفاده می کنید، نمی توانید مقداری را به صورت مستقیم به عنوان ورودی پارامتر زمان فراخوانی متد استفاده کنید، یعنی برای ورودی تنها مجاز به استفاده از نام یک متغیر که تعریف کرده اید خواهید بود، کد زیر صحیح نبوده و کامپایل نمی شود:

private static void Main(string[] args)
{
    Do(ref 18);
}

کلمه کلیدی دیگری که در پارامترها کاربرد دارد، کلمه کلیدی out می باشد. نحوه کارکرد out دقیقاً مانند ref می باشد، با این تفاوت که زمانی که یک پارامتر از نوع out تعریف می شود، حتماً باید داخل بدنه متد آن را مقدار دهی کرد، اما ref به این صورت نیست. کد زیر را در نظر بگیرید:

private static void Main(string[] args)
{
    int sum;
    int substact;
    Calc(12, 3, out sum, out substact);
    Console.WriteLine(sum);
    Console.WriteLine(substact);
}

public static void Calc(int num1, int num2, out int sum, out int substract)
{
    sum = num1 + num2;
    substract = num1 - num2;
}

در متد Calc، دو پارامتر sum و substract از نوع out تعریف شده اند، یعنی حتماً باید این دو پارامتر داخل بدنه متد مقدار دهی شوند. در صورتی که یکی از پارامترها مقدار دهی نشود، با پیغام خطا روبرو خواهید شد. یکی از مهمترین کاربردهای out زمانی است که می خواهید متدی بیش از یک خروجی داشته باشد.


آرایه به عنوان ورودی و خروجی متد


موقعیتی را در نظر بگیرید که می خواهید میانگین اعداد ورودی یک متد را حساب کرده و به عنوان خروجی برگردانید. یک راه حل این کار استفاده از آرایه به عنوان ورودی متد می باشد. به مثال زیر دقت کنید:

private static void Main(string[] args)
{
    var average = Average(new[] {2, 6, 8, 1, 2});
    Console.WriteLine(average);
}

public static int Average(int[] numbers)
{
    var sum = 0;
    foreach (var number in numbers)
        sum += number;
    return sum/numbers.Length;
}

در کد بالا، پارامتر ورودی Average از نوع آرایه تعریف شده و میانگین اعداد آرایه حساب شده و به عنوان خروجی باز گردانده خواهند شد. حال فرض کنید که می خواهیم تعداد 10 عدد از اعداد اول را حساب کرده و به عنوان خروجی برگردانیم. در این موقعیت می توانیم خروجی متد را از نوع آرایه در نظر بگیریم:

private static void Main(string[] args)
{
    foreach (var primeNumber in PrimeNumbers())
    {
        Console.WriteLine(primeNumber);
    }
}

public static int[] PrimeNumbers()
{
    var numbers = new int[10];
    var number = 1;
    var index = 0;
    while (index < 10)
    {
        if (IsPrime(number))
            numbers[index++] = number;
        number++;
    }
    return numbers;
}

public static bool IsPrime(int number)
{
    if (number <= 3)
        return true;
    for (int counter = 2; counter < number; counter++)
    {
        if (number%counter == 0)
            return false;
    }
    return true;
}

کمی در مورد کد بالا توضیح می دهیم، ابتدا از متد IsPrime شروع می کنیم. این متد بررسی می کند که عدد ارسال شده توسط پارامتر به این متد اول هست یا خیر (عدد اول عددی است که تنها بر خودش و یک بخش پذیر باشد). متد PrimeNumbers، تعداد 10 عدد از اعداد اول را حساب کرده و داخل یک آرایه 10 خانه ای قرار می دهد. دقت کنید که داخل این متد، از متد IsPrime استفاده کرده ایم، دلیل شکستن کد به دو متد، افزایش خوانایی برنامه می باشد. پس از محاسبه اعداد، آرایه را به عنوان خروجی متد بر میگردانیم. همانطور که مشاهده می کنید، خروجی متد PrimeNumbers از نوع آرایه می باشد.


کلمه کلیدی params


در قسمت بررسی آرایه ها به عنوان ورودی و خروجی، برنامه ای نوشتیم که اعدادی را به عنوان ورودی متد دریافت کرده و سپس میانگین آن را حساب می کرد. برای اینکار از آرایه به عنوان ورودی استفاده کردیم. اما راه حل دیگر آن استفاده از کلمه کلیدی params می باشد. بوسیله این کلمه کلیدی می توانید 1 تا n مقدار را برای آن پارامتر مشخص کنیم بدون اینکه در هنگام فراخوانی متد آرایه ای تعریف کنیم. در حقیقت مقادیر به صورت پشت سر هم و با علامت , از هم جدا می شوند. کد میانگین را تغییر داده و از کلمه کلیدی params استفاده می کنیم:

private static void Main(string[] args)
{
    var average = Average(2, 8, 9, 3, 1 , 3);
    Console.WriteLine(average);
}

public static int Average(params int[] numbers)
{
    var sum = 0;
    foreach (var number in numbers)
        sum += number;
    return sum / numbers.Length;
}


به این موضوع دقت داشته باشید که تنها آخرین پارامتر متد می تواند از نوع params باشد و تنها یک پارامتر، یعنی شما نمی توانید دو پارامتر برای متد را از نوع params تعریف کنید.


آشنایی با مفهوم Method Overloading


زمانی که شما متدی را تعریف می کنید، می توانید چندین متد همنام دیگر با آن متد داشته باشید، به شرط آنکه تعداد و نوع ورودی های آن ها با هم متفاوت باشند.در مثال زیر، یک متد و Signature آن نوشته شده اند:

public static int Multiply(int number1, int number2) // Signature => int Multiply(int, int)
{

}

برای آشنایی بیشتر فرض کنید، متدی نوشته ایم که نام و نام خانوداگی را به عنوان ورودی دریافت کرده و یک پیغام مناسب در خروجی چاپ می کند:

private static void Main(string[] args)
{
    DisplayMessage("Hossein", "Ahmadi");
}

public static void DisplayMessage(string firstName, string lastName)
{
    Console.WriteLine("Welcome dear " + firstName + " " + lastName + ".");
}

حال نسخه دیگری از همین متد اما با سه پارامتر ورودی تعریف می کنیم:

private static void Main(string[] args)
{
    DisplayMessage("Hossein", "Ahmadi", 29);
}

public static void DisplayMessage(string firstName, string lastName)
{
    Console.WriteLine("Welcome dear " + firstName + " " + lastName + ".");
}

public static void DisplayMessage(string firstName, string lastName, byte age)
{
    DisplayMessage(firstName, lastName);
    Console.WriteLine("You are " + age + " years old!");
}

در این حالت، ما می توانیم هر دو نسخه متد DisplayMessage را صدا بزنیم. یعنی هم بدون پارامتر Age و هم با پارامتر Age. زمانی که متدی دارای Overload باشد، Intellisense در Visual Studio زمان فراخوانی متد، لیستی از تمام Overload های آن متد را به ما نمایش می دهد:


p1


متد WriteLine که در کدها از آن استفاده می کنیم نیز دارای Overload های بسیاری است:

p2



متدهای بازگشتی یا Recursive Methods


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

n! = n * (n - 1) * (n - 2) * ... * 1

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

private static void Main(string[] args)
{
    Console.WriteLine(Fact(4));
}

public static int Fact(int num)
{
    if (num == 1)
        return num;
    return num*Fact(num - 1);
}

همانطور که مشاهده می کنید، داخل بدنه متد Fact، مجدد آن را فراخوانی کردیم. دقت کنید که زمان فراخوانی مجدد متد، از پارامتر num یک عدد کم کردیم و به عنوان پارامتر استفاده کردیم. همچنین داخل بدنه متد، باید شرطی وجود داشته باشد که از تکرار بی نهایت متد جلوگیری کند، در غیر اینصورت با خطای Stack Overflow مواجه خواهید شد. هر بار فراخوانی یک واحد از num کم می شود و زمانی که پارامتر num به مقدار 1 برسد، فراخوانی مجدد انجام نشده و زنجیر وار، فراخوانی متدها به پایان خواهد رسید.

تا این قسمت با مفاهیم ابتدایی زبان سی شارپ آشنا شدیم. در قسمت های بعدی برنامه نویسی شئ گرا را آغاز می کنیمو مباحثی که تا کنون آموختیم را به برنامه های کاربردی تر بسط خواهیم داد. امیدارم که تا این لحظه از آموزش مورد توجه دوستان قرار گرفته باشد. ITPRO باشید

نویسنده : حسین احمدی
منبع : جزیره برنامه نویسی وب سایت توسینسو
هرگونه نشر و کپی برداری بدون ذکر منبع و نام نویسنده دارای اشکال اخلاقی است
برچسب ها
ردیف عنوان
1 دوره آموزشی .NET Framework و زبان برنامه نویسی سی شارپ - مقدمه
2 آموزش سی شارپ - قسمت اول :: معرفی و بررسی ابزارهای مورد نیاز دوره
3 آموزش زبان سی شارپ - قسمت دوم :: آشنایی با .NET Framework و ساختار آن (بخش اول)
4 آموزش زبان سی شارپ - قسمت دوم :: آشنایی با .NET Framework و ساختار آن (بخش دوم)
5 آموزش زبان سی شارپ - قسمت سوم :: آشنایی اولیه با محیط Visual Studio و نوشتن اولین برنامه
6 آموزش زبان سی شارپ - قسمت چهارم :: آشنایی با ساختار برنامه ها و کامپایلر زبان سی شارپ
7 آموزش زبان سی شارپ - قسمت پنجم :: آشنایی با دستورات کنسول و متغیرها
8 آموزش زبان سی شارپ - قسمت ششم :: نوع های داده اولیه
9 آموزش زبان سی شارپ - قسمت هفتم :: آشنایی با عملگرهای زبان سی شارپ
10 آموزش زبان سی شارپ - قسمت هشتم :: آشنایی با دستورات کنترلی و حلقه ها (بخش اول)
11 آموزش زبان سی شارپ - قسمت هشتم :: آشنایی با دستورات کنترلی و حلقه ها (بخش دوم)
12 آموزش زبان سی شارپ - قسمت هشتم :: آشنایی با دستورات کنترلی و حلقه ها (بخش سوم)
13 آموزش زبان سی شارپ - قسمت هشتم :: آشنایی با دستورات کنترلی و حلقه ها (بخش چهارم)
14 آموزش زبان سی شارپ - قسمت نهم :: آشنایی با آرایه ها و دستور foreach
15 آموزش زبان سی شارپ - قسمت دهم :: آشنایی با متدها در زبان سی شارپ (بخش اول)
16 آموزش زبان سی شارپ - قسمت دهم :: آشنایی با متدها در زبان سی شارپ (بخش دوم)
17 آموزش برنامه نویسی شئ گرا در زبان سی شارپ - قسمت یازدهم :: مقدمه ای بر برنامه نویسی شئ گرا
18 آموزش برنامه نویسی شئ گرا در زبان سی شارپ - قسمت دوازدهم :: آشنایی با کلاس، اشیاء و فضاهای نام
19 آموزش برنامه نویسی شئ گرا در زبان سی شارپ - قسمت سیزدهم :: آشنایی با فیلدها و رفتارها
20 آموزش برنامه نویسی شئ گرا در زبان سی شارپ - قسمت چهاردهم :: آشنایی با Property ها
21 آموزش برنامه نویسی شئ گرا در زبان سی شارپ - قسمت پانزدهم :: آشنایی با سازنده ها و روش های ایجاد اشیاء
22 آموزش برنامه نویسی شئ گرا در زبان سی شارپ - قسمت شانزدهم :: وراثت یا Inheritance
23 آموزش برنامه نویسی شئ گرا در زبان سی شارپ - قسمت هفدهم :: آشنایی با مفهوم Polymorphism
24 آموزش برنامه نویسی شئ گرا در زبان سی شارپ - قسمت هجدهم:: کلاس های abstract و sealed
25 آموزش برنامه نویسی شئ گرا در زبان سی شارپ - قسمت نوزدهم :: سازنده ها در وراثت، کلمه کلیدی protected و فیلدهای readonly
26 آموزش برنامه نویسی شئ گرا در زبان سی شارپ - قسمت بیستم :: کلاس های static و partial و Extension Method ها
27 آموزش برنامه نویسی شئ گرا در زبان سی شارپ - قسمت بیست و یکم :: Reference Types و Value Types
28 آموزش برنامه نویسی شئ گرا در زبان سی شارپ - قسمت بیست و دوم :: آشنایی با کاربرد interface ها
29 آموزش برنامه نویسی شئ گرا در زبان سی شارپ - قسمت بیست و سوم :: آشنایی با مفاهیم Inversion of Control و Dependency Injection
30 آموزش برنامه نویسی شئ گرا در زبان سی شارپ -قسمت بیست و چهارم :: آشنایی با مفهوم Type Casting و انواع Cast ها
31 آموزش برنامه نویسی شئ گرا در زبان سی شارپ -قسمت بیست و پنجم :: آشنایی با operator overloading و تعریف cast ها
32 آموزش برنامه نویسی شئ گرا در زبان سی شارپ -قسمت بیست و ششم :: مفاهیم boxing و unboxing
33 آموزش برنامه نویسی شئ گرا در زبان سی شارپ -قسمت بیست و هفتم :: قابلیت Generics
34 آموزش برنامه نویسی شئ گرا در زبان سی شارپ -قسمت بیست و هشتم :: نکات تکمیلی Generic ها، کلاس List و کلاس Dictionary
35 آموزش زبان سی شارپ -قسمت بیست و نهم (پایانی): استثناء ها (Exceptions) و مدیریت خطاها در سی شارپ
دوره مجموعه کل دوره
مطالب مرتبط

در حال دریافت اطلاعات

نظرات
  • سلام
    مهندس واقعا ممنون از مطالب و آموزشی که شروع کردید
    اما واقعا خیلی دیر دیر آپدیت میکنید
    میتونید زمانبدی این آموزش رو بهمون بگید؟
    بازم ممنون از زحماتتون
  • سلام، در حال حاضر به خاطر اینکه درگیر به روز رسانی نرم افزار وب سایت و تکمیل ویژگی های اون هستم فرصت نوشتن ندارم، اما به زودی با اتمام کارهای نسخه سوم، بخش برنامه نویسی شئ گرا رو شروع خواهیم کرد.

    ممنون از شما
  • قسمت های 10 کمی سخت بود.
    در قسمت قبل گفتید متد Main سطح دسترسی public دارد، ولی اینجا از private استفاده شده،دلیلش چیه؟

    ممنون بابت آموزش

  • با سلام و سپاس از مطالب مفید سایت

    یک نکته در "آشنایی با مفهوم Method Overloading" نیاز به اصلاح دارد

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

    اما مفهوم Method Overloading در واقع تفاوت در Signature متدها است. یعنی در تعداد و نوع پارامترهای ورودي متد می باشد و به نوع خروجی متد ارتباطی ندارد.

    به عنوان نمونه:
    غیر مجاز
    
    public int sum(int a, int b)
            {
                return a + b;
            }
    
            public long sum(int a, int b)
            {
                return a + b;
            }
    //----------------------------------------
     مجاز
    public int sum(int a, int b)
            {
                return a + b;
            }
    
            public int sum(int a, int b, int c)
            {
                return a + b + c;
            }
    
            public long sum(int a, byte b)
            {
                return a + b;
            }
    

  • سلام و تشکر، موردی که اشاره کردید در متن اصلاح شد.

برای ارسال نظر ابتدا به سایت وارد شوید