روشهای ارسال پارامتر با مقدار ( Value) و ارجاع (Reference) در#C

شنبه 10 بهمن 1394

در این مقاله قصد داریم دو روش ارسال پارامتر در دات نت فریم ورک #C ، که شامل By Value و By Reference هستند را معرفی و آنها را با هم مقایسه میکنیم .

روشهای ارسال پارامتر با  مقدار ( Value) و ارجاع (Reference) در#C

روش های ارسال پارامتر

 در دات نت فریم ورک، تمام اشیاء به طور پیش فرض با By Valueارسال میشوند  . نوع اولیه یک value type  (مانند int   ، char، , double و غیره)و نوع اولیه Reference شامل ( کلاس ،interface, delegate, string ، و غیره)است.

ارسال پارامتر By Value در Value Types

در روش  by-value  از مقدار argument یک کپی گرفته شده و به پارامتر داده می‌شود. از این‌رو، هر بلایی که سر پارامتر آورید هیچ تغییری روی argument صورت نمی‌گیرد . وارسال به روش value parameter به صورت پیش فرض می باشد .

نمونه های زیر را در نظر بگیرید:

در مرحله اول، استفاده از value type  را نشان میدهیم

    int num1 = 5;  
    int num2 = num1;  
    num2 = 10;  
    Console.WriteLine(num1);  

 بنظر شما چه چیزی در کنسول چاپ میشود؟

 جواب درست 5 است،چرا که int  یک value type است که  توسط پارامتر value ارسال میشود،در اینجا ،ابتدا مقدار 5 را در num1 میریزد .زمانی که ما num2 میسازیم و  num1را به آن اختصاص میدهیم. مقدار num1 در  num2 کپی میشود اگر ما مقدار num2 را تغییردهیم ،num1هیچ تغییری نمیکند. برای مثال:

 متدی برای ست کردن  مقدار 10  برای یک متغیر از نوع int ایجاد کردیم .

    private void ChangeValue(int i)   
    {  
        i = 10;  
    }  

آن را با استفاده از مثال قبلی صدا میزنیم:

    int num1 = 5;  
      
    ChangeValue(num1);  
      
    Console.WriteLine(num1);  

در حال حاظر خروجی کنسول چه خواهد بود؟

بله خروجی  هنوز همان 5 است. قبلا گفته شده که مقدار ها کپی میشوند بنابراین زمانی که متد ChangeValue صدا زده میشود، مقدار num1  کپی شده ، بنابراین تغییر i  ، num1 را تغییر نمیدهد  .

نمودار / نمایش تصویری از انتقال توسط مقدار در Value Types

نمایش هندسی  ارسال پارامتر با مقدار

ارسال پارامترBy Value در Reference Types

نیاز است بدانید که چرا باید value type را توسط reference ارسال کنیم. به‌صورت کلی، دو دلیل برای این‌کار وجود دارد: اجازه دادن به متد تا بتواند محتوای argument اش را تغییر دهد. اجازه دادن به متد برای اینکه بتواند بیشتر از یک مقدار را return کند

 در کلاس User که از نوع مرجع به عنوان کلاسهای Reference Types است:

    public class User  
    {  
        public int UserID  
        {  
            get;  
            set;  
        }  
        public string Name  
        {  
            get;  
            set;  
        }  
    }  

یک نمونه ایجاد کرده و خصوصیتها را تنظیم میکنیم و خصوصیت Name  را تغییر میدهیم ، انچه را که در کنسول چاپ شده را بررسی میکنیم.

User objUser = new User()   
{  
    UserID = 1,  
        Name = "kolsum Ebrahimi"  
};  
User objUser2 = objUser;  
objUser2.Name = "Mina Bahri"; 

هنگامی که ما  نمونه ای از کلاس User ایجاد میکنیم ، برای اینکه بتوانیم از انها بیشتر استفاده کنیم ،یک شیء در حافظه (heap) ایجاد می شود و حافظه به آن اختصاص داده میشودو  reference در آن مکان از حافظه که حافظه مرجع objUser  قرار دارد ذخیره میشود (عمدتا پشته)، در غیر این در حافظه ذخیره نمیشود ، بنابراین ما نیاز به نگه داشتن یک مرجع برای عملکرد عملیات های مختلف در حافظه داریم.

هنگامی که ما objUser را مساوی objUser 2 مرجع اختصاص میدهیم ، کپی  از objUser 2  را در  objUser1  میریزد ، که در حال حاضر دو نسخه جداگانه  از مرجع  وجود دارد که  هر دو آنها به یک محل از حافظه اشاره میکنند.بنابراین با تغییر  مقدارName  ،مقدار در شیء  حافظه ،مرجعobjUser تغییر خواهد کرد، از این رو Mina bahri در کنسول چاپ خواهد شد . 

همچنین از heap برای ذخیره سازی؛محتویات شیء از نوع reference-typedو هر چیزی که قرار است در شیء از نوع reference-typed ذخیره شود، استفاده میشود.

 نمایش هندسی ارسال پارامتر  مقدار در   Reference Types

شما میتوانید همان رفتار را با استفاده از متد مشاهده کنید.

public static void ChangeName(User user)  
{  
    user.Name = "Mina Bahri";  
} 

ما آن را با  را صدا میزنیمobject state، و همان رفتار را به ما نشان میدهد:

    User objUser = new User()  
    {  
        UserID = 1, Name = "kolsum Ebrahimi"  
    };  
      
    ChangeName(objUser);  
      
    Console.WriteLine(objUser.Name);  

هنگامی که ما در حال ارسال مرجع objUser از  شی User به متد  ChangeName هستیم،  مرجع در محل حافظه قرار دارد که متد شیء user در آن محل کپی شده است، و هر دو به یک محل از حافظه اشاره میکنند ، بنابراین تغییر مقدار خصوصیت Name  مقدار  شیء در حافظه مرجع objUser و user را تغییر خواهند داد، از این رو "Mina Bahri" در کنسول چاپ خواهد شد.

در اینجا  نمایش هندسی از آن نمایش داده میشود :

زمانی که ChangeName(objUser) صدا زده میشود، آن هم به همان محل از حافظه اشاره میکند، و خصوصیت  Name از شی User را به "Mina bahri"   اصلاح میکند .

به نظر شما اگر داخل متد  ChangeName  مقدار user رابا null  ست کنیم چه اتفاقی می افتد:

    public static void ChangeName(User user)  
    {  
        user = null;  
    }  

و آن را در objUser صدا میزنیم:

    User objUser = new User()  
    {  
        UserID = 1,  
            Name = "kolsum Ebrahimi"  
    };  
      
    ChangeName(objUser);  
    Console.WriteLine(objUser.Name);  

اگر شما فکر میکنید که null برای  Reference استثنا است ،در اشتباه هستید،و اگر فکر میکنید که جواب خروجی  kolsum Ebrahimi است ، جواب درست است و شما کاملا ارسال پارامتر با Reference در مقادیر C# را متوجه شده اید.

مشاهده نمایش تصویری برای درک بهتر:

ارسال پارامتر توسط Reference

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

اگر ما می خواهیم  objUser را با null بسازیم، باید آن را با استفاده از متد By Reference ، در C # با کلمه کلیدی ref انجام شود. ما از نمونه های فوق دوباره استفاده می کنیم اما این بار از By Reference  استفاده خواهیم کرد و خواهید دید چه اتفاقی می افتد و شما می توانید تفاوت بین این دو را درک کنید.

ارسال پارامتر توسط Reference در Value Types

ما از همان مثال بالا استفاده میکنیم ، اما در اینجا از ارسال By Referenc استفاده میکنیم . برای این کار، اول از همه، برای تغییر  متد (ChangeValue (INTI   بهChangeValue(ref inti)، باید کلمه کلیدی ref را به پارامتر ورودی اضافه کنیم .به این معنی که در هنگام فراخوانی این متد، ارگومان باید با Referenc ارسال شود :

    private void ChangeValue(ref int i)  
    {  
        i = 10;  
    }  

در حال حاضر ما ازهمان کد بالا استفاده میکنیم اما  مجبور به استفاده از کلمه کلیدی ref را در هنگام صدا زدن  پارامترهای که با متد  by reference ارسال میشوند،هستیم.

    int num1 = 5;  
      
    ChangeValue(ref num1);  
      
    Console.WriteLine(num1);  

خروجی 10 است ،چرا که از کلمه کلیدیref  در ChangeValue برای دریافت پارامتر استفاده کرده ایم. در اینجا  آدرس حافظه  num1  به عنوان آرگومان است به همین دلیل اصلاح مقدار i در  تغییر num1 و همچنین در ارسال by reference  در محل جدید ازحافظه در پارامتر متد منعکس میشود .

ارسال پارامتر By Reference در Reference Types

یک reference به‌عنوان argument به متد داده شده و کپی این reference به پارامتر فرستاده می‌شود. درون متد، پارامتر به همان شیءای رجوع می‌کند که argument رجوع می‌کند. این یعنی اگر هر تغییری روی پارامتر انجام دهید، این تغییر روی argument نیز تاثیر می‌گذارد زیرا هردو به یک شیء وصل هستند و تغییر هرکدام، شیء را تحت تاثیر قرار می‌دهد

وقتی یک وهله از reference-type ایجاد شود، یک فضا برای object و فضایی دیگر برای اشاره‌گر به آن شیء در حافظه اصلی ذخیره می‌شود. در واقع دو فضا از حافظه برای ذخیره سازی آنها اشغال می‌شود.
ما در حال حاضر همان چیز را با Reference Types چک میکنیم ، و همان رفتار برای Reference Types  در نظر میگیریم :

    public static void ChangeName(ref User user)   
    {  
        user = null;  
    }  

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

User objUser = new User()  
{  
    UserID = 1,  
        Name = "kolsum Ebrahimi"  
};  
  
ChangeName(objUser);  
Console.WriteLine(objUser.Name); 

وقتی ما user  را مساوی با null قرار میدهیم در داخل ChangeName نیز objUser نیز  میشود null  به خاطر ارسال مقدار با  by Reference، محل دیگری از  حافظه برای مرجع جدید ایجاد می شود که اشاره به همان شی که توسط reference ارسال میشود ،دارد در کل .برای ذخیره اشاره گر دو فضا در حافظه ذخیره میشود ،یکی برای اشاره به شی و دیگری برای ذخیره کردن شی  .

آموزش سی شارپ

برنامه نویسان

نویسنده 3355 مقاله در برنامه نویسان
  • C#.net
  • 10k بازدید
  • 5 تشکر

کاربرانی که از نویسنده این مقاله تشکر کرده اند

در صورتی که در رابطه با این مقاله سوالی دارید، در تاپیک های انجمن مطرح کنید