فرستادن Reference به متدها
تا این قسمت از زنگ سیشارپ، پارامترهایی که به متد داده میشدند همهگی value type بودند (مانند int یا double و…) اما علاوه بر value type شما میتوانید از reference type نیز بهعنوان پارامتر استفاده کنید. اینکار به یک شیء اجازه میدهد تا بتواند به یک متد فرستاده شود.
به مثال زیر توجه کنید:
using System; class MyClass { string Name; string Surname; int Age; // Constructor public MyClass(string name, string surname, int age) { Name = name; Surname = surname; Age = age; } // Return true if ob contains the same values as the invoking object. public bool SameAs(MyClass ob) { if (Name == ob.Name && Surname == ob.Surname && Age == ob.Age) return true; else return false; } // Make a copy of ob public void Copy(MyClass ob) { Name = ob.Name; Surname = ob.Surname; Age = ob.Age; } public void Show() { Console.WriteLine(" Name: {0}, Surname: {1}, Age: {2}", Name, Surname, Age); } } class PassOb { static void Main() { MyClass ob1 = new MyClass("Damon", "Salvatore", 22); MyClass ob2 = new MyClass("Stefan", "Salvatore", 21); Console.WriteLine("ob1: "); ob1.Show(); Console.WriteLine("ob2: "); ob2.Show(); Console.WriteLine(); if (ob1.SameAs(ob2)) Console.WriteLine("ob1 and ob2 have the same values."); else Console.WriteLine("ob1 and ob2 have different values."); // Now, make ob1 a copy of ob2 ob1.Copy(ob2); Console.WriteLine(); Console.WriteLine("ob1 after copy: "); ob1.Show(); Console.WriteLine(); if (ob1.SameAs(ob2)) Console.WriteLine("ob1 and ob2 have the same values."); else Console.WriteLine("ob1 and ob2 have different values."); } }
متد ()SameAs و متد ()Copy هرکدام یک Reference را بهعنوان argument دریافت میکنند (همانطور که میدانید Reference آدرس یک شیء در حافظه است). متد ()SameAs مقادیر Name، Surname و Age را از متدی که فراخوانی شده با مقادیر Name، Surname و Age شیء ob که به متد داده شده است، مقایسه میکند و در صورت یکسان بودن این مقادیر،true برمیگرداند. متد ()Copy نیز مقادیر شیء ob را به مقادیر شیء فراخوانیشده اختصاص میدهد. همانطور که میبینید به همان روشی که value type ها به متدها داده میشوند، reference type ها نیز داده شدهاند.
از دو طریق Argument ها به parameter ها فرستاده میشوند:
- Call-by-value
- Call-by-reference
در روش اول (call-by-value) از مقدار argument یک کپی گرفته شده و به پارامتر داده میشود. از اینرو، هر بلایی که سر پارامتر آورید هیچ تغییری روی argument صورت نمیگیرد.
به مثال زیر توجه کنید:
using System; class MyClass { static void Main() { int a = 5; Change(a); Console.WriteLine(a); } static void Change(int x) { x++; } }
مقدار a برابر با ۵ است.argument متد ()Change مقدارa است. از این مقدار یک کپی گرفته شده و به پارامتر این متد (x) فرستاده میشود. هنگامیکه درون این متد مقدار x افزایش مییابد. تغییر x هیچ تاثیری روی مقدار a نمیگذارد. به شکل زیر توجه کنید:
همانطور که میبینید با تغییر پارامتر، مقدار a هیچ تغییری نمیکند زیرا کپی مقدار a در x قرار دارد و ایندو کاملاً مستقل از هم هستند.
در روش دوم (call-by-reference) یک reference بهعنوان argument به متد داده شده و کپی این reference به پارامتر فرستاده میشود. درون متد، پارامتر به همان شیءای رجوع میکند که argument رجوع میکند. این یعنی اگر هر تغییری روی پارامتر انجام دهید، این تغییر روی argument نیز تاثیر میگذارد زیرا هردو به یک شیء وصل هستند و تغییر هرکدام، شیء را تحت تاثیر قرار میدهد.
به مثال زیر توجه کنید:
// Objects are passed by reference. using System; class Test { public int a, b; public Test(int i, int j) { a = i; b = j; } /* Pass an object. Now, ob.a and ob.b in object used in the call will be changed. */ public void Change(Test ob) { ob.a = ob.a + ob.b; ob.b = -ob.b; } } class CallByRef { static void Main() { Test ob = new Test(15, 20); Console.WriteLine("ob.a and ob.b before call: " + ob.a + " " + ob.b); ob.Change(ob); Console.WriteLine("ob.a and ob.b after call: " + ob.a + " " + ob.b); } }
همانطور که میبینید تغییر در پارامتر متد ()Change باعث تغییر مقادیر شیء میشود.
همانطور که میبینید تغییرات در متد ()Change موجب تغییر شیءای میشود که argument نیز به آن رجوع میکرد.
استفاده از پارامترهای ref و out
همانطور که گفته شد، value type ها از طریق مقدارشان به یک متد فرستاده میشوند و تغییر در پارامترهایی که argument را دریافت میکنند، در argument تغییری ایجاد نمیکند. سیشارپ به شما اجازه میدهد که این رفتار را از طریق کلمات کلیدی ref و out تغییر دهید. در سیشارپ این امکان وجود دارد که value type را توسط reference ارسال کنید. اینکار به متد این امکان را میدهد تا بتواند argument را تغییر دهد.
پیش از اینکه به چگونگی مکانیسم ref و out بپردازیم نیاز است بدانید که چرا باید value type را توسط reference ارسال کنیم. بهصورت کلی، دو دلیل برای اینکار وجود دارد: اجازه دادن به متد تا بتواند محتوای argument اش را تغییر دهد. اجازه دادن به متد برای اینکه بتواند بیشتر از یک مقدار را return کند.
ref Parameter Modifier
اغلب شما میخواهید یک متد بتواند روی argument هایی که به آن داده میشود تغییرات اعمال کند. سادهترین مثال میتواند متد ()Swap باشد که دو متغیر را میگیرد و مقادیر آنها را جابهجا میکند. در حالت عادی این امکان وجود ندارد که متدی بنویسید تا عملیات swap را انجام دهد اما کلمه کلیدی ref این مشکل را حل میکند.
ref modifier موجب میشود سیشارپ بهجای call-by-value یک call-by-reference ایجاد کند.ref modifier زمانی که متد ساخته و صدا زده میشود، مشخص میشود. بهتر است با یک مثال موضوع را روشنتر کنیم. برنامه زیر یک متد به اسم ()Sqr دارد که این متد مقدار داده شده به آن را به توان ۲ میرساند:
// Use ref to pass a value type by reference. using System; class RefTest { // This method changes its argument. Notice the use of ref. public void Sqr(ref int i) { i = i * i; } } class RefDemo { static void Main() { RefTest ob = new RefTest(); int a = 10; Console.WriteLine("a before call: " + a); ob.Sqr(ref a); // notice the use of ref Console.WriteLine("a after call: " + a); } }
همانطور که میبینید ref قبل از پارامتر و قبل از argument آمده است و موجب شده که مقدار a بعد از فراخوانی متد تغییر کند.
به مثال زیر توجه کنید:
// Swap two values. using System; class ValueSwap { // This method now changes its arguments. public void Swap(ref int a, ref int b) { int t; t = a; a = b; b = t; } } class ValueSwapDemo { static void Main() { ValueSwap ob = new ValueSwap(); int x = 10, y = 20; Console.WriteLine("x and y before call: " + x + " " + y); ob.Swap(ref x, ref y); Console.WriteLine("x and y after call: " + x + " " + y); } }
همانطور که میبینید بعد از فراخوانی متد ()Swap مقدار متغیرهای x و y عوض شده است. نکتهی مهم در مورد ref این است که argument ای که از طریق ref ارسال میشود باید از پیش تعریف شده باشد. به این دلیل که پارمتر مطمئن شود مقداری که دریافت میکند، مقداری معتبر است. بنابراین نمیتونید مستقیماً مثلاً مقدار ۱۰ را در argument بنویسید.
out Parameter Modifier
گاهی نیاز دارید که از پارامتر reference استفاده کرده تا مقداری را از یک متد دریافت کنید اما مقداری را به آن ندهید. برای مثال تصور کنید متدی دارید که یک سری عملیات (مثل باز کردن سوکت یک شبکه)را انجام میدهد و در نهایت کد موفقیت یا عدم موفقیت را به پارامتر reference باز میگرداند. در اینطور موارد، اطلاعات ارسالی به متد وجود ندارد اما یکسری اطلاعات هستند که متد آنها را باز میگرداند. مشکل این سناریو این است که ref parameter ابتدا بایستی در یک متغیر مقداردهی اولیه شود بنابراین با استفاده از ref parameter بایستی یک argument با یک مقدار ساختگی (که یک کار بیهوده است) را ارسال کنیم تا بهاصطلاح دهان compiler را ببندیم که خطایی به برنامه نگیرد. خوشبختانه سیشارپ پیشنهاد بهتری برای این مشکل دارد: out parameter
پارامتر out مشابه پارامتر ref است اما یک تفاوت دارد. پارامتر out فقط مقداری را از متد باز میگرداند و اطلاعات ارسالی به متد ندارد. نیازی نیست متغیری که بهعنوان out argument بهکار میرود، در قسمت فراخوانی متد، مقداردهی اولیه شود چراکه متد، خودش یک مقدار را به آن متغیر میدهد. علاوهبراین، درون متد، پارامتر out بهصورت unassigned در نظر گرفته شده است. بدین معنی که فرض بر این است متغیر مربوطه مقداردهی اولیه نشده است و متد باید خودش مقداری را به متغیر اختصاص دهد. با این تفاسیر بعد از فراخوانی متد، out parameter شامل یک مقدار خواهد بود.
به مثال زیر توجه کنید:
class OutExample { static void Method(out int i) { i = 44; } static void Main() { int value; Method(out value); // value is now 44 } }
درون متد Method پارامتر out شامل مقدار ۴۴ است. این مقدار از طریق متغیر i وارد متغیر value میشود. همانطور که میبینید value مقداردهی اولیه نشده و پس از فراخوانی متد، مقدار ۴۴ به آن اختصاص داده شده است.
یکی دیگر از کاربردهای out parameter modifier برای این است که یک متد بهجای یک خروجی، بتواند چندین خروجی داشته باشد.
به مثال زیر دقت کنید:
using System; class OutReturnExample { static void MyMethod(out int i, out string s1, out string s2) { i = 180; s1 = "I've been returned."; s2 = "This example uses out to return three variables."; } static void Main() { int i; string str1, str2; MyMethod(out i, out str1, out str2); Console.WriteLine(i); Console.WriteLine(str1); Console.WriteLine(str2); } }
همانطور که میبینید از طریق out parameter modifier توانستیم ۳ مقدار را (بهجای ۱ مقدار) return کنیم. البته اگر return-type متد را بهجای void مثلاً bool در نظر میگرفتیم میتوانستیم علاوه بر آن سه مقدار، یک مقدار بولین هم برگردانیم و جمعاً ۴ مقدار را return کنیم.
استفاده از ref و out تنها به فرستادن value type ها محدود نمیشود بلکه هنگام فرستادن reference نیز میتوانند مورد استفاده قرار گیرد. این کار به یک متد اجازه میدهد تا بتواندreference ای که به شیءای رجوع کرده را تغییر دهدتا به شیء دیگری رجوع کند.در مثال زیر از ref reference parameter استفاده شده تا دو reference که به ۲ شیء جدا رجوع میکنند را با هم تعویض کند:
using System; class MyClass { static void Main() { Swap swapRef1 = new Swap(2, 3); Swap swapRef2 = new Swap(4, 5); Console.Write("swapRef1 befor change: "); swapRef1.Show(); Console.Write("swapRef2 befor change: "); swapRef2.Show(); Console.WriteLine(); swapRef1.swapping(ref swapRef1, ref swapRef2); Console.Write("swapRef1 after change: "); swapRef1.Show(); Console.Write("swapRef2 after change: "); swapRef2.Show(); } } class Swap { int a, b; public Swap(int a, int b) { this.a = a; this.b = b; } public void swapping(ref Swap ob1, ref Swap ob2) { Swap t; t = ob1; ob1 = ob2; ob2 = t; } public void Show() { Console.WriteLine("a = {0}, b = {1}", a, b); } }
در این مثال، متد ()Swap اشیای argument هایی که به متد پاس داده شدهاند را با هم تعویض میکند. قبل از فراخوانی متد ()Swap متغیر swapRef1 به شیءای با مقادیر ۲ و ۳ ومتغیر swapRef2 به شیءای با مقادیر ۴ و ۵ رجوع میکند اما بعد از فراخوانی ()Swap متغیر swapRef1 به شیءای با مقادیر ۴ و ۵ ومتغیر swapRef2 به شیءای با مقادیر ۲ و ۳ رجوع میکند. اگر ref را حذف کنید تغییرات اعمال شده فقط درون متد ()Swap میماند و در بیرون از متد تاثیری ندارد.
استفاده از argument به تعداد دلخواه
هنگامیکه یک متد میسازید میدانید که چه تعداد پارامتر دارید و از آنطرف چه تعداد argument قرار است که دریافت کنید اما همیشه قضیه به این صورت نیست. بهعنوان مثال متدی را در نظر بگیرید که میانگین را حساب میکند. آیا همیشه باید ۲ یا ۳ عدد را به آن داده تا میانگینشان را بدست آورد؟ مسلماْ نه! اینچنین متدی باید هر تعداد که argument به آن داده میشود میانگیناش را بدست آورد و حد و مرزی نداشته باشد. ممکن است یکبار به آن ۲ مقدار داده شود، بار دیگر ۳ یا ۷ مقدار داده شود تا میانگین آنها را حساب کند. برای این منظور باید از کلمهی کلیدی params استفاده کنید.params modifier برای تعریف آرایهای از پارامترها بهکار میرود که میتواند صفر یا بیشتر از صفر argument را دریافت کند. سایز این آرایه با توجه به تعداد argument هایی که به متد داده شده تعیین میشود.
به مثال زیر توجه کنید:
using System; class MyClass { static void Main() { ParamTest ob = new ParamTest(); Console.WriteLine(ob.Average(2, 3, 5, 6)); Console.WriteLine(ob.Average(2, 3.5)); double[] myArray = { 5, 8, 6, 12, 15.5, 7 }; Console.WriteLine(ob.Average(myArray)); } } class ParamTest { public double Average(params double[] nums) { double result = 0; for (int i = 0; i < nums.Length; i++) { result += nums[i]; } return result / nums.Length; } }
به نحوهی استفادهیparams در متد ()Average توجه کنید. همانطور که میبینید در هر بار تعداد متفاوتی از مقادیر نوع double را به متد پاس دادهایم و در قسمت آخر آرایهای از جنس double را به متد دادهایم تا میانگین آن حساب شود.
حمید
9 February 2013
تشکر و سپاس
mandana
10 February 2013
سلام
باسپاس وتشکر
1)مهندس حان تاخیر یکم زیاد نشده است در ارایه مطالب ببخشیدا
2)linqوado,netهم آموزش می دهید
مسعود درویشیان
10 February 2013
سلام آره این مدت یکم تاخیر افتاد باید ببخشید اما همون هفتهای یکبار پخش میشه ازین به بعد
فقط LINQ رو توی زنگ سیشارپ میگیم.
s.saber
13 February 2013
سلام و خسته نباشد ، واقعا کلاسهای منحصر به فردی ارائه میدهید خیلی جالب اند .
استاد ببخشید هدفتون از ارائه محیط کنسول سی شارپ چیه ، چرا با محیط ویژوالی کار نمیکنید بهتره ؟؟
ببخشید درنظر دارید که در آینده محیط ویژوالی سی شارپ را ارائه دهید ؟؟
مسعود درویشیان
13 February 2013
سلام. هدف ما از این مجموعهی آموزشی فقط یادگیری اصل زبان سیشارپ هست. چون بعد از یادگیری زبان سیشارپ دیگه میتونید توی محیطهای دلخواهتون (مثل وب، موبایل، بازی و…) ازش استفاده کنید. اون محیطها فقط تکنیک خاص خودشون رو دارن که راحت میتونید (توی یه مدت زمان کم) باهاشون آشنا بشید. زبون همون زبون سیشارپ هست…
s.saber
14 February 2013
ممنون ، من خودم الان رو پروژه پایانی دانشگاهم با ویژوال سی شارپ کار میکنم و چیزی هم از برنامه نویسی با سی شارپ سر درنمیارم ! اگر با این کلاس های آموزشی شما پیش برم روی موفقیتم تو پروژه تاثیر داره ؟؟
منظورم اینه اینجا کد نویسی را یاد بگیرم و اونجا با محیط ویژوالی ادغام کنم ، مشکلی که برام پیش نمی یاد ؟؟
یا نظر شما چیه ، چون وقت هم کمه ! بنظر شما چکار کنم اگه راهنمایی است لطف کنید.
با تشکر
مسعود درویشیان
14 February 2013
اگه زمانتون خیلی کمه که فکر نمیکنم وقت کنید اول اینو یاد بگیرید بعد توی یه محیط ویژوال پروژه پیاده کنید. (البته همهچیز بستگی به خودتون و زمانتون داره)
اما اگه بخواین یه پروژه مثل “انتخاب واحد دانشجو” یا “آژانس” یا برنامههایی در این سطح رو توی محیط کنسول پیاده کنید فعلاً تا همین قسمت رو بخونید میتونید انجام بدید.
s.saber
15 February 2013
ممنون از پاسختون ، خب فرصت تا 30 خرداده و پروژه ام سیستم حسابداری دانشگاست ، بنظرتو چکار کنم ؟؟
ممنون
مسعود درویشیان
15 February 2013
اگه تا ۲ ماه آینده زنگ سیشارپ رو دنبال کنید (و واقعاً یاد بگیرید و تمرین کنید) و اون یکی ۲ ماه آخر هم توی یه محیط ویژوال تمرین کنید به احتمال زیاد میتونید پروژه رو انجام بدید. اما بازم میگم، همهچی بستگی به (تمرین) خودتون داره…
مهدی
14 February 2013
سلام و خسته نباشید آقای درویشیان؛
منظور شما از این مبحث گفته هاتون چیه:
“متد ()SameAs مقادیر Name، Surname و Age را از متدی که فراخوانی شده با مقادیر Name، Surname و Age شیء ob که به متد داده شده است، ”
یعنی چی؟ وقتی که خودش متد هست به چه نحوه دیگه ای توسط متدی دیگر فراخوانی می شود؟ لطفا مبسوط تر توضیح بدید.
مسعود درویشیان
14 February 2013
متد ()SameAs کارش اینه که یه شیء میگیره، فیلدهای شیءای رو که گرفته با فیلدهای همون شیءای که متد ()SameAs از اون داره صدا زده میشه، مقایسه میکنه (یعنی فیلدهای ۲ تا شیء رو مقایسه میکنه) اگه برابر بود که true اگرم نه که false برمیگردونه
مهدی
15 February 2013
در واقع پارامترهاش فیلدهای یک کلاس هستند(در متد ()SamesAs )
در متد Copy و در این خط ;( ob1.Copy(ob در واقع فیلدهای ob1 ریخته میشن تو ob ؟
طبق این خطوط:
Name = ob.Name;
Surname = ob.Surname;
Age = ob.Age;
مسعود درویشیان
15 February 2013
نه! همیشه سمت راست مساوی ریخته میشه توی سمت چپ مساوی یعنی فیلدهای ob ریخته میشوند توی ob1
داوود
22 February 2013
سلام آقا مسعود؛ وقتت بخیر
مسعود جان در این عبارت که نوشتید:
“در این مثال، متد ()Swap اشیای argument هایی که به متد پاس داده شدهاند را با هم تعویض میکند.”
آیا به جای متد swap نباید می نوشتید متد swapping ؟ آخه متد swap که فقط کار مقدار گذاری رو داره انجام میده؟؟
همچنین میشه بگید این خط دقیقاً چه کاری انجام میده؟
[C#]Swap t [/C#]
مسعود درویشیان
23 February 2013
آره ببخشید اشتباه نوشتم :) swapping درسته
Swap t هم که مثل یه متغیر واسط هست برای جابهجایی اون دو مقدار دریافتی…
محمد فر
8 April 2013
سلام.در مورد مثال اول سئوال داشتم:
چرا تو متد از کلمه this استفاده نکردید؟
مثلا توی متذ sameAs()
مسعود درویشیان
8 April 2013
چون نیازی نبوده! وقتی مینویسیم Name، مگر چندتا فیلد Name توی اون کلاس (MyClass) وجود داره؟ فقط یکی!
اما وقتی میخوایم به فیلد Name شیء ob که به متد ()SameAs داده شده دسترسی داشته باشیم، از طریق ob.Name بهش دسترسی داریم. ولی اگه بنویسیم Name یا this.Name منظورمون فیلد Name همین کلاسی است که الان داخلشیم (که میشه فیلد Name شیءای که از روی این کلاس میسازی و ازش استفاده میکنی)
اگه مشکلی بود بگین تا واضحتر بگم
محمد فر
10 April 2013
با تشکر از توضیحاتتون.متوجه شدم
محمد فر
10 April 2013
سلام استاد.
در مورد مثال swap که نوشتید سئوال داشتم.
من تا الان فکر می کردم اگه یه شی رو به یک متد پاس کنیم ادرس شی درون پارامتر شی کپی میشه.مثلا ما یه شی می سازیم به این صورت:
Swap swapRef1;
در اینجا ما یه متغییر از نوع swap تعریف کردیم.یعنی swapRef1 داره به یک مکانی از حافظه اشاره میکنه یعنی یک اشاره گر است.حالا ما در خط بعدی به swapRef1 حافظه اختصاص می دهیم(یعنی به member هاش)
swapRef1 = new Swap(2, 3);
حالا چیزی که من برداشت کردم اینه که وقتی این شی رو به متد swapping می فرستیم ادرس این شی است که درون پارامتر b1 یا b2 این متد ریخته میشه. در این خط این اتفاق می افتد:
swapRef1.swapping(swapRef1,swapRef2);
یعنی با اجرا این خط b1 ادرس swapRef1 را در خودش دارد یعنی دارد به این شی اشاره می کند و b2 هم به swapRef2.
با این توضیحات من متوجه نشدم که چه نیازی به استفاده از کلمه کلیدی ref در متد می باشد.خلاصه کلام مگر یک class یک refrence type نمی باشد پس باید شامل دو قسمت باشد یکی ادرس و دیگری مقدار.
امیدورام متوجه سئوالم شده باشید.می بخشید که زیاد نوشتم.
مسعود درویشیان
12 April 2013
آره این آدرس شیء هست که جابهجا میشه
اگر از ref استفاده نکنی، آدرس این دو شیءای که ساختی و پاس دادی به متد، با هم تعویض نمیشه. یعنی نمیره این آدرسها رو از reference تغییر بده!
محمد فر
12 April 2013
میشه بیشتر توضیح بدید.متوجه نشدم
مسعود درویشیان
17 April 2013
ببین محمد جان، اگه دقت کنی ما به دو طریق argument ها رو به پارامترها میفرستیم: call-by-value و call-by-reference
که call-by-value برای value type ها هست (مثل int و double و…) و call-by-reference برای reference type ها (مثل اشیایی که خودت تعریف میکنی)
پس اگه یه عدد (مثلاً از جنس int) رو به پارامترها بفرستی داری از روش call-by-value استفاده میکنی که موجب میشه هر تغییری توی متد (روی عددی که گرفتی) انجام بدی، این تغییر توی همون متد بمونه و روی همون پارامتر اعمال بشه. چرا؟؟؟ چون وقتی از روش call-by-value استفاده میکنی یه کپی از argument به parameter داده میشه و توی متد همین کپیای رو که داره تغییر میده و دیگه کاری به اون متغیر اصلی (argument) نداره. حالا اگه میخوای تغییراتی که روی پارامتر اعمال میکنی، روی argument هم اعمال بشه، از ref استفاده میکنی.
ولی اگه یه reference رو پاس بدی داری از call-by-reference استفاده میکنی یعنی مستقیماً میتونی مقادیر یه شیء رو تغییر بدی. اما توی این مورد swap که قرار آدرس دوتا شیء رو جابهجا کنی به ref نیاز داری چون به مقدار داخل شیء کاری نداری و صرفاً داری آدرسشون رو جابهجا میکنی
محمد فر
13 April 2013
یعنی اگه از ref استفاده نکنیم ادرس اشیا داخل متد جابجا میشن و دیگر ادرس argument ها جابجا نمیشن؟
علیرضا اسکندرپور شوفری
28 April 2013
تا اونجا که من متوجه شدم، دو کلیدواژه ref و out برای call-by-reference بی تاثیر هست. (من تست کردم با ref و هردو با اون یا بدونه اون مقدار شیء تغییر میکنه). اینطوری برداشت کردم که چون قبلا هم گفته شده که reference وقتی میدی خود شیء رو نمیدی بلکه آدرسش رو میدی. پس شیء سر جاش هست و هر تغییری از طریق آدرس صورت بگیره روی شیء مستقیما تاثیر میذاره. اکر مثلا اینطوری بود که شیء رو میداد یا یه کپی از شیء میگیرفت و آدرس کپی رو میداد اونوقت استفاده از out و ref مخصوصا معنا میگرفت. (البته به این گفته های خودم شک دارم)
دو کلیدواژه برای call-by-value معنی دارن که یه کپی از مقدار همیشه به آرگومان داده میشه. وقتی تغییری ایجاد کنی روی کپی داری تغییر میدی. واسه اینکه روی اصلی تغییر ایجاد کنی باید از ref یا out بسته به نیازت استفاده کنی.
اگر درکیات من اشتباه بود لطفا اصلاحش شده اش رو بگید. مرسی
Mersad
17 August 2013
سلام جناب درویشیان
من مقاله ی شما رو به همراه کامنت هاش چندبار خوندم و مثال هاشو چندبار تمرین کردم ولی بنده هم ابهام آقای محمدفر و آقای اسکندری پور برام بوجود اومده.
مگه وقتی شی رو به یک متد میفرستیم، خودش call-by-reference نیست؟ دیگه چه نیازی به کلمه ی ref هست؟
منظورم اینه که وقتی یک شی رو میفرستیم، یه کپی ازش رو که نمیفرسته، بلکه آدرس اون شی رو میفرسته، و حالا با استفاده از آدرسش، هر تغییری که ایجاد کنیم، روی اون شی و در نتیجه روی argument هم ایجاد میشه.
حالا با این تفاسیر چرا برای ارسال argumnet هایی که شی هستن (حاوی آدرس شی هستن) باید از ref استفاده کنیم؟
تو مواردی که الان بیان کردم، کدوم قسمتش غلط هست که نمیتونم مثال Swap رو درک کنم که چرا وقتی ref رو برمیداریم جابجایی اشیا اتفاق نمیوفته؟
خیلی ممنون
مسعود درویشیان
25 August 2013
ببینید ما قرار نیست توی اون مثال بیایم محتوای اشیاء رو تغییر بدیم. ما دوتا شیء داریم که میخواهیم فقط آدرسهاشون رو با هم عوض کنیم. همین! واسه اینکه آدرسهاشون هم جابهجا کنیم به ref نیاز داریم چون در غیر اینصورت تغییرات توی همون متد باقی میمونه
a-p
6 August 2014
بسم الله الرحمن الرحیم
سلام
می توانید توضشح و مثال بیشتری در مورد outبزنید
داود چهریان
11 December 2014
سلام استاد درویشیان
واقعا توضیحات عالی و کامل هستند
تشکر فراوان از شما
komeil asadi
14 December 2014
salam ostad, vaghan behtar az har kelasi tozih midid.
tashakor az zahamate shoma
rahimi
16 December 2014
سلام ممنونم بابت آموزش های کامل و مفیدتون…فقط یه سوال من هر چی گشتم آموزش توابع رو پیدا نکردم خیلی بهش احتیاج دارم توی کدوم قسمت توابع آموزش داده شده؟؟؟
یه سوال دیگه:توی توابع از کجا باید بفهمیم بازگشتی هست یا نه؟؟یا چه موقع از void باید استفاده کنیم؟؟
محمد
23 September 2015
سلام. تابع بازگشتی بصورتی است که یه مقدار رو خودش درون خودش صدا میزنه. در واقع به خودش میفرسته.
در مواقعی از تابع void استفاده میشه که تابع مقدار برگشتی ندارد. یعنی نمیخواید از تابع چیزی بفرستید. و صرفا یه سری کار درون خودش انجام میده
سارا
13 January 2015
مرسی عالی بود
مری
25 July 2015
استاد مگه string شامل ریفرنس ها نمیشد ؟ پس چرا ارگومان تغیر نمیکنه ؟
علي
20 May 2016
با سلام.من يك ماتريس ٢بعدي تعريف كرده ام كه دائم در حال تغيير است.در حِين تغيير اين ماتريس را ذخيره ميكنم.ولي در آخر كه به اين ماتريس هاي ذخيره شده رجوع ميكنم همگي برابر ماتريس كنوني است.اگر ميشود راهنمايي كنيد