روشهای ارسال پارامتر با مقدار ( Value) و ارجاع (Reference) در#C
شنبه 10 بهمن 1394در این مقاله قصد داریم دو روش ارسال پارامتر در دات نت فریم ورک #C ، که شامل By Value و By Reference هستند را معرفی و آنها را با هم مقایسه میکنیم .
روش های ارسال پارامتر
در دات نت فریم ورک، تمام اشیاء به طور پیش فرض با 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 در کنسول چاپ خواهد شد .
نمایش هندسی ارسال پارامتر مقدار در 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 ارسال میشود ،دارد در کل .برای ذخیره اشاره گر دو فضا در حافظه ذخیره میشود ،یکی برای اشاره به شی و دیگری برای ذخیره کردن شی .
- C#.net
- 10k بازدید
- 5 تشکر