در این مقاله، همچنان ما قصد داریم در مورد متدها اما از یک منظر متفاوت صحبت کنیم. ما میخواهیم یاد بگیریم که چطور آرگومانها را با استفاده از کلمات کلیدی ref
و out
پاس دهیم.
این مقاله، سرفصلی از دوره آموزشی زیر میباشد:
- راه اندازی محیط توسعه
- Data Type ها، Declaration ها و تعریف متغیرها در #C
- عملگرها در #c
- تبدیل نوع های داده ای
- ورودی و خروجی در #c
- کار با رشته ها
- شرطها در #c
- حلقه ها (While، Do-While، For)
- مدیریت خطاها
- Access Modifier ها
- متدها
- کلمات کلیدی Ref و Out
- بازگشت و متدهای بازگشتی
- آرایه ها (آرایه های تک بعدی و چند بعدی)
- کار با فایلها، StreamWriter و StreamReader
- کار با فایلها، File و Directory
اگر می خواهید محتویات کامل این دوره را ببینید ، می توانید بر روی لینک مبانی #c کلیک کنید.
اگر میخواهید سورس مثالهای این مقاله را دانلود کنید بر روی لینک سورس کلمات کلیدی Ref و Out کلیک کنید.
این مقاله شامل چند قسمت میشود:
در مقاله قبلی، ما زمان صدا زدن متدهایمان، آرگومانهای value type را پاس میدادیم. چرا نوع آرگومان اینجا مهم است؟
خب زمانیکه ما آرگومانی از نوع int، double، decimal و غیره (value type های پایه) را پاس میدهیم، در حقیقت مقدار واقعی آن را پاس نمیدهیم بلکه یک کپی از آن را پاس میدهیم. این به این معنی است که مقادیر اصلی ما، داخل متدها تغییر نمیکنند زیرا ما یک کپی جدید از مقدار اصلی را پاس میدهیم. در نتیجه ، تمام عملیات درون یک متد بر روی مقدار کپی شده اجرا می شوند.
ما میتوانیم این را با ذکر یک مثال نشان دهیم:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
class Program { public static void ChangeAndWrite(int number) { number = 10; Console.WriteLine($"Inside ChangeAndWrite method, number value is: {number}"); } static void Main(string[] args) { int number = 5; Console.WriteLine($"Value of the number prior to ChangeAndWrite call is: {number}"); ChangeAndWrite(number); Console.WriteLine($"Value of the number after the ChangeAndWrite call is: {number}"); Console.ReadKey(); } } |
همانطور که میبینیم، مقدار متغیر number، فقط داخل متد ChangeAndWrite تغییر کرده است. اما مقدار اصلی، همان مقدار قبل از فراخوانی متد ChangeAndWrite است و هیچ تغییری نمیکند و مجددا این به این خاطر است که ما دقیقا کپی آن مقدار اصلی را پاس میدهیم.
استفاده از کلمات کلیدی Ref و Out
ما میتوانیم این رفتار پیش فرض را تغییر دهیم. اگر ما میخواهیم که مقادیر اصلی را داخل متدهایمان تغییر دهیم، میتوانیم این کار را با استفاده از کلمات کلیدی ref
و out
داخل امضای متد و همچنین در حین فراخوانی متد انجام دهیم.
تنها در صورتی میتوانیم از کلمه کلیدی ref استفاده کنیم که از متغیری که به عنوان یک آرگومان استفاده میکنیم قبلا از فراخوانی متد، مقداردهی شده باشد. با استفاده از کلمه کلیدی out ، نیازی نیست که قبل از فراخوانی متد، متغیر را مقدار دهی کرده باشیم، اما باید آن را داخل متد مقدار دهی کنیم.
بنابراین اجازه بدید ساده ترش کنیم. اگر بخواهیم مقدار موجود از یک متغیر را داخل یک متد تغییر دهیم از کلمه کلیدی ref استفاده میکنیم، اما اگر بخواهیم یک مقدار کاملا جدید را به متغیر مورد نظر در داخل متد اختصاص دهیم، سپس باید از کلمه کلیدی out استفاده کنیم.
مثال 1 برای Value Type
در مثال قبلی دیدیم که اگر از کلمات کلیدی ref یا out استفاده نکنیم، متغیرهای value type چطور رفتار میکنند. حال در این مثال، میخواهیم نحوه رفتار متغیرهای value type را زمانیکه از این کلمات کلیدی استفاده میکنیم را ببینیم:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
class Program { public static void ChangeRef(ref int numberRef) { numberRef = 25; Console.WriteLine($"Inside the ChangeRef method the numberRef is {numberRef}"); } public static void ChangeOut( out int numberOut) { numberOut = 60; Console.WriteLine($"Inside the ChangeOut method the numberOut is {numberOut}"); } static void Main(string[] args) { int numberRef = 15; Console.WriteLine($"Before calling the ChangeRef method the numberRef is {numberRef}"); ChangeRef(ref numberRef); Console.WriteLine($"After calling the ChangeRef method the numberRef is {numberRef}"); Console.WriteLine(); int numberOut; Console.WriteLine("Before calling the ChangeOut method the numberOut is unassigned"); ChangeOut(out numberOut); Console.WriteLine($"After calling the ChangeOut method the numberOut is {numberOut}"); Console.ReadKey(); } } |
این کاملا واضح است. اگر ما از کلمه کلیدی ref یا out بر روی متغیرهای value type استفاده کنیم در نتیجه مقدار اصلی آن تغییر میکند. تنها تفاوت آن این است که با کلمه کلیدی out ما میتوانیم متغیرهای بدون مقدار دهی را استفاده کنیم.
مثال ۲ برای Reference Type
ما یاد گرفتیم که reference type، مقدارش را داخل مکان حافظه خودش ذخیره نمیکند، بلکه آدرس اشاره گر به آن مکان حافظه که مقدار درونش ذخیره شده است را در خود ذخیره میکند. بنابراین زمانیکه یک آرگومان را به عنوان یک reference type به متد مورد نظر میفرستیم و آن پارامتر را تغییر میدهیم، مقدار اصلی نیز تغییر میکند. این به این دلیل است که ما کپی آن مقدار را نمیفرستیم بلکه آدرس اشاره گر به آن مقدار اصلی را ارسال میکنیم. این دقیقا مانند حالتی است که از کلمه کلیدی ref به همراه value type ها استفاده می کنیم.
اینجا هنوز میتوانیم از کلمه کلیدی ref به همراه reference type ها نیز استفاده کنیم، اگر بخواهیم یک آبجکت جدید با یک آدرس یکسان را ایجاد کنیم.
حال همه اینها را در این مثال ببینیم:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
class Program { public static void ChangeColor(Pen pen) { pen.Color = Color.Green; Console.WriteLine($"Inside the ChangeColor method the color is {pen.Color}"); } public static void CreateNewObjectWithoutRef(Pen pen) { pen = new Pen(Color.Red); Console.WriteLine($"Inside the CreateNewObjectWithoutRef method the color of new pen object is {pen.Color}"); } public static void CreateNewObjectWithRef(ref Pen pen) { pen = new Pen(Color.Yellow); Console.WriteLine($"Inside the CreateNewObjectWithRef method the color of new pen object is {pen.Color}"); } static void Main(string[] args) { Pen pen = new Pen(Color.Blue); Console.WriteLine($"Before ChangeColor method: {pen.Color}"); ChangeColor(pen); Console.WriteLine($"After the ChangeColor method: {pen.Color}"); Console.WriteLine(); Console.WriteLine($"Before CreateNewObjectWithoutRef method: {pen.Color}"); CreateNewObjectWithoutRef(pen); Console.WriteLine($"After CreateNewObjectWithoutRef method: {pen.Color}"); Console.WriteLine(); Console.WriteLine($"Before CreateNewObjectWithRef method: {pen.Color}"); CreateNewObjectWithRef(ref pen); Console.WriteLine($"After CreateNewObjectWithRef method: {pen.Color}"); Console.ReadKey(); } } |
در اولین متد، ما از کلمه کلیدی ref استفاده نمیکنیم. در نتیجه مقدارمورد نظر تغییر می کند زیرا ما کپی آدرسی را که مقدار اصلی در آن ذخیره شده است را پاس میدهیم. در متد دوم، مقدار اصلی تغییر نمیکند. زیرا ما یک آبجکت جدید داخل متد ایجاد کردیم، بنابراین آدرس حافظه جدید اختصاص داده می شود. اما در مثال سوم، ما از کلمه کلیدی ref استفاده میکنیم و در نتیجه مقدار اصلی تغییر میکند. چرا؟ چون با کلمه کلیدی ref، ما داریم همان آدرس را به یک آبجکت جدید کپی میکنیم.
نتیجه گیری
حالا ما میدانیم که چطور از کلمات کلیدی ref و out به همراه value type و reference type ها استفاده کنیم. این یک ویژگی کاملا مفید در #C است. بنابراین دانستن کار کردن با این کلمات کلیدی، یک مزیت برای توسعه دهندگان به شمار می آید.
در پست بعدی، ما در مورد بازگشت و متدهای بازگشتی صحبت میکنیم.