📮 پاس دادن پارامترها در #C :
راز بزرگ کپی شدن "مقدار" و "رفرنس"
یکی از بنیادیترین مفاهیمی که هر توسعهدهنده #C باید بهش مسلط باشه، نحوه پاس دادن پارامترها به متدهاست.
قانون اصلی اینه: در #C، همه چیز به صورت پیشفرض بر اساس مقدار (Pass-by-Value) پاس داده میشه. اما این جمله ساده، برای Value Type و Reference Type دو معنی کاملاً متفاوت داره!
1️⃣سناریو اول: پاس دادن Value Type (کپی کامل)
وقتی یه Value Type (مثل int, struct, bool) رو به یه متد میدید، انگار یه فتوکپی کامل از مقدار اون متغیر میگیرید و اون کپی رو به متد میدید.
متد با اون کپی هر کاری بکنه، اصل سند شما دست نخورده باقی میمونه.
int x = 8;
// یک کپی از مقدار 8 به متد فرستاده میشه
Foo(x);
// x اینجا هنوز همون 8 باقی مونده!
Console.WriteLine(x); // خروجی: 8
static void Foo(int p)
{
// p فقط یک کپی از x هست و در یک جای جدا در حافظه قرار داره
p = p + 1;
Console.WriteLine(p); // خروجی: 9
}
2️⃣سناریو دوم: پاس دادن Reference Type (کپی کلید!) 🔑
اینجا داستان کاملاً فرق میکنه و همونجاییه که خیلیها به اشتباه میفتن.
وقتی یه Reference Type (مثل یه class یا StringBuilder) رو به متد پاس میدید، شما خودِ آبجکت (خونه) رو بهش نمیدید، بلکه یه کپی از کلید (رفرنس) اون خونه رو بهش میدید.
این یعنی حالا دو تا کلید داریم که هر دو، یک در رو باز میکنن!
این رفتار دو تا نتیجه مهم داره:
اگه محتوای خونه رو عوض کنیم، برای همه عوض میشه:
متد با کلید کپی شده میتونه بره تو همون خونه و دکوراسیون رو عوض کنه. این تغییر روی آبجکت اصلی تأثیر میذاره چون هر دو کلید یه خونه رو باز میکنن.
اگه کلید کپی شده رو عوض کنیم، کلید اصلی ما امنه:
ولی اگه متد، خودِ کلید کپی شده رو با یه کلید دیگه عوض کنه (مثلاً fooSB = null)، شما هنوز کلید اصلی خودتون رو دارید و آبجکت اصلی شما null نمیشه.
StringBuilder sb = new StringBuilder("original");
Foo(sb);
// محتوای sb تغییر کرده چون متد، دکوراسیون خونه رو عوض کرد
Console.WriteLine(sb.ToString()); // خروجی: original-test
static void Foo(StringBuilder fooSB)
{
// ۱. با کلید کپی شده، محتوای آبجکت اصلی رو تغییر میدیم
fooSB.Append("-test");
// ۲. خودِ کلید کپی شده رو null میکنیم.
// این کار هیچ تأثیری روی متغیر sb اصلی نداره.
fooSB = null;
}🤔 حرف حساب و تجربه شما
درک این تفاوت، کلید اصلی جلوگیری از باگهای غیرمنتظرهایه که توش دادهها به شکلی که انتظار ندارید، تغییر میکنن.
آیا این رفتار برای پاس دادن Reference Typeها براتون کاملاً روشن بود؟ یا تا حالا با مشکلی مواجه شدید که توش یه آبجکت داخل یه متد تغییر کرده و شما رو غافلگیر کرده باشه؟
خب، اینجا که نمیشه همه حرفا رو زد! 😉
ادامهی بحث، سوالات، غر زدنها و گپ و گفتهای خودمونی، فقط تو گروه.
[C# Geeks Hangout]
🔖 هشتگها :
#CSharp
#Parameters
#ReferenceTypes #ValueTypes