PDA

View Full Version : سوال: انتساب در متغییر های رشته ای



alireza_tavakol
یک شنبه 04 مرداد 1388, 02:31 صبح
اگه واقعا متغییر های رشته ای از نوع Reference types هستند و در عمل انتساب ارجاع به منبع میشوند به نظر شما خرجی کد زیر چیست؟


String a = "Hello";
String b = a;
b = "Hi";
MessageBox.Show(a);


من انتظار دارم خروجی کد بالا کلمه Hi باشه ولی بر خلاف تصور من کلمه Hello نمایش داده میشه ! کسی میدونه علت وقوع این حادثه چیه؟

hozouri
یک شنبه 04 مرداد 1388, 07:27 صبح
دوست عزیز این دستور داره درست انجام میشه یه تریس کن یا autos بگیر :



String a = "Hello"; // a = Hello
String b = a; // a=Hello , b = Hello
b = "Hi"; // a=Hello , b=Hi


فکر کنم شما چیزی دیگه ای مد نظرتونه

alireza_tavakol
یک شنبه 04 مرداد 1388, 10:02 صبح
همون طوری که خودتون می دونید امکان تعریف کردن اشارگر به شی از جنس کلاس string (متغییر رشته ای ) وجود نداره چون خون متغییر رشته ، اشارگری به بخشی از حافظه heap است یکی از خصوصیات اشارگر ها اینکه در هر جایی از برنامه مقدار متغییر تغییر بدهند سراسری اعمال میشه

برای روشن تر شدم حرفام مقاله زیر رو download کنید و صفحه شماره 10 رو مطالعه کنید

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

alireza_tavakol
یک شنبه 04 مرداد 1388, 11:04 صبح
برای روشن شدن مطلب یک مثال میزنم

شما 2 عدد جعبه متن و یک دکمه بگذار روی فرمت و بعد در رویداد کلیک دکمه کد زیر رو بنویس و نتیجه رو مشاهده کن


textBox2 = textBox1;
textBox2.Text = "Hi";

همون طوری که دیدین کلمه Hi در جعبه متن textBox1 اعمال میشه در صورتی که در کد مقدار text جعبه متن دوم تغییر کرده علت روخ داد این واقعه خط اول است چون
textBox1 نومه ای از کلاس textBox است و چون کلاسها از نوع Reference types هستند در همه انتساب ارجاع به منبع میشوند و به خاطر همین خصوصیتشان است که اشارگر ها برای این نوع داده ها قابل پیاده سازی نیستند
حالا من تعجب میکنم که اگه میگیم string هم کلاس و کلاس ها Reference types حساب میشن پس چرا از این قاعده مستثنا است؟

Unknownlive
یک شنبه 04 مرداد 1388, 11:30 صبح
اگر می خواهید مشکل شما حل بشه کتاب John Sharp & Jon jagger را بخوانید
در ضمن دستور درست کار می کنه شما نگاه کنید متغیر a را چاپ کردید خود در a هم کلمه Hello نسبت داده شده

alireza_tavakol
یک شنبه 04 مرداد 1388, 12:21 عصر
برای روشن شدن مطلب یک مثال میزنم

شما 2 عدد جعبه متن و یک دکمه بگذار روی فرمت و بعد در رویداد کلیک دکمه کد زیر رو بنویس و نتیجه رو مشاهده کن


textBox2 = textBox1;
textBox2.Text = "Hi";

همون طوری که دیدین کلمه Hi در جعبه متن textBox1 اعمال میشه در صورتی که در کد مقدار text جعبه متن دوم تغییر کرده علت روخ داد این واقعه خط اول است چون
textBox1 نومه ای از کلاس textBox است و چون کلاسها از نوع Reference types هستند در همه انتساب ارجاع به منبع میشوند و به خاطر همین خصوصیتشان است که اشارگر ها برای این نوع داده ها قابل پیاده سازی نیستند
حالا من تعجب میکنم که اگه میگیم string هم کلاس و کلاس ها Reference types حساب میشن پس چرا از این قاعده مستثنا است؟

میگم نظر شما ( Unknownlive ) درباره مثالی که زدم روی textBox ها چیه ! توی اون مثال من مقدار textBox2 رو تغییر میدم ولی مقدار textBox1 تغییر میکنه.

پس چرا وقتی من مقدار متغییر b رو تغییر میدم مقدار متغییر a عوض نمیشه؟ این دو تا متغییر که دارن به یک جا از حافظه اشاره میکنن؟

SMRAH1
یک شنبه 04 مرداد 1388, 14:25 عصر
سلام

دوست من دو نوع string و struct به صورت value Type هستند (بخصوص string که با اینکه کلاس هست ولی یک استثنا است) نه refrence type .

موفق باشید

alireza_tavakol
یک شنبه 04 مرداد 1388, 15:16 عصر
سلام

دوست من دو نوع string و struct به صورت value Type هستند (بخصوص string که با اینکه کلاس هست ولی یک استثنا است) نه refrence type .

موفق باشید

من با این حرف شما کلا" مخالفم لطف کنید منبع علمی که این حرف رو زده معرفی کنید چون توی اون مقاله ای که توی پست سوم همین تاپیک پیوست کردم دقیقا به این نکته اشاره شده که string یک نوع reference type ، ولی شما داری کلا" در خلاف جهت نظریه پردازی میکنی

حالا فرض که حرف شما درست باشه پس بی زحمت بفرمایید چطوری میشه یک اشاره گر به یک متغییر رشته ای تعریف کرد یا به منبع یک متغییر رشته ای دسترسی پیدا کرد؟

RED-C0DE
یک شنبه 04 مرداد 1388, 15:40 عصر
سلام

دوست من دو نوع string و struct به صورت value Type هستند (بخصوص string که با اینکه کلاس هست ولی یک استثنا است) نه refrence type .

موفق باشید
اشتباه است!!!


string (یا همون System.String) یک Reference Type هستش...یکی از دلایل ، اینه ک بتونه اون رشته کاراکترهاش رو در Heap نگه داره ، بخاطر حجم بالایی ک می تونه داشته باشه..
نگهداری اون تعداد زیاد کاراکتر با حجم محدودی ک Stack داره غیر ممکنه و همینطور Performance (عملیات رشته ای معروف) رو ب شدت پایین می یاره...


From MSDN :

string
The string type represents a string of Unicode characters. string is an alias for System.String in the .NET Framework.

Although string is a reference type, the equality operators (== and !=) are defined to compare the values of string objects, not references (7.9.7 String equality operators). This makes testing for string equality more intuitive.


System.String
(http://msdn.microsoft.com/en-us/library/362314fe(VS.71).aspx)

نوشته های John Skeet نویسنده کتاب "#C in Depth" در مورد String :
http://www.yoda.arachsys.com/csharp/strings.html

String ها Immutable هستن و نمی شه مقادیرشون رو تغییر داد..می شه مثلا با استفاده از متد Replace یک مقدار رو جایگزین کرد، ولی برای اینکار یک string ِ جدید گرفته می شه و مقدار قبلی + جایگزینی با مقدار جدید یک رشته جدید می سازن و این عمل انجام می شه.. (برای عملیات رشته ای زیاد پیشنهاد شده از StringBuilder استفاده بشه)

در مورد سوال :

اگه واقعا متغییر های رشته ای از نوع Reference types هستند و در عمل انتساب ارجاع به منبع میشوند به نظر شما خرجی کد زیر چیست؟

کد:
String a = "Hello";
String b = a;
b = "Hi";
MessageBox.Show(a);
من انتظار دارم خروجی کد بالا کلمه Hi باشه ولی بر خلاف تصور من کلمه Hello نمایش داده میشه ! کسی میدونه علت وقوع این حادثه چیه؟

String ها Reference Type هستن و در این شکی نیست، در اینجا "Hello" در Heap قرار داره و هر دو ب اونجا Reference دارن، ولی برخی از اعمال معروف ک مخصوص Reference Typeها هستن مثل انتساب و یا مقایسه برای String استثنا قائل شدن (پیاده سازی جداگانه ای دارن) ، مثلا برای عمل مقایسه بین دو تا String ( == ) بجای مقایسه Reference دو object ، مقادیر یا همون محتوای اصلی اونها (مثل دو تا آرایه از نوع Char) با هم مقایسه می شن(بر خلاف وقتی ک مقایسه برای دو تا Reference Type ِ معمولی انجام می شه و Reference ِ اونها مقایسه می شه)...
و یا برای انتساب ، در واقع یک کپی از محتوایی ک داره منتسب می شه ، گرفته می شه، و برای متغیر جدید (در اینجا b ) در Heap یکجا رزرو می شه و از این ب بعد مکان این دو متغیر در Heap جدا می شه ( البته اگر قرار باشه تغییری انجام بشه در رشته اصلی)

hozouri
یک شنبه 04 مرداد 1388, 15:42 عصر
دوست عزیز فکر کنم جواب شما توی تعریف کلاس ها هست ما می تونیم انواعی از کلاس ها داشته باشیم.

یک String درسته که یک کلاسه اما از انواع sealed هست درصورتی که یک textbox یک کلاس معمولی است

alireza_tavakol
یک شنبه 04 مرداد 1388, 16:13 عصر
با تشکر از گفته ها جامع و کامل RED-C0DE

حالا مسئله ای که مطرح میشه اینکه چطوری میشه :

برای دسترسی به منبع متغییر های value Type نوع داده pointers وجود داره
برای دسترسی به منبع متغییر های Reference types از عملگر = استفاده میشه

ولی این طوری که من از بحث برداشت داشتم عملگر = برای متغییر های رشته با توجه به این Reference types هستند خارج از قاعده عمل میکند و نوع داده pointers هم که قابل پیاده سازی برای Reference types نیست ، پس این برنامه نویس بیچاره باید چی کار کنه تا مستقیما" به منبع یک متغییر رشته ای دسترسی پیدا کنه؟:عصبانی++:

SMRAH1
دوشنبه 05 مرداد 1388, 15:57 عصر
سلام

1) پیوست پست سه رو دیدم.کتاب جالبی است (اطلاعات رو به شکل فشرده ارایه داده).با این حال باید یادمون باشه که وحی منزل نیست!برای نمونه عکس صفحه 10 رو پیوست کردم تا نشون بدم اطلاعات این کتاب + پست اول ، که کاملا صحیح است، و همچنین پست 9 (نوشته دوست خوبم Red_code به نقل از MSDN و توضیحات تکمیلی آن) به راحتی اشتباه بودن این نکته در کتاب رو مشخص می کنه!
2) شاید این تلقی اشتباه بودن از اشتباه در نوشتار من بوده است در واقع جمله رو دوباره می نویسم (برخی مفاهیم رو به دلیل اینکه فکر کردم نیاز نیست به شکل خود بخود حذف کرده بودم!)
«دوست من دو نوع string و struct در رفتار به صورت value Type هستند (بخصوص string که با اینکه کلاس هست و تمام کلای های Refrence Type ولی یک استثنا است) نه مانند refrence type .» که درواقع همان نکاتی بود که جناب RED-CODe در فرموده بودند با این تفاوت که خیلی تلگرافی است! با این حال قبول دارم که اشتباه از من بوده است که نتوانستم مفاهیم رو خوب انتقال دهم.
3) در مورد دسترسی مستقیم به حافظه (برای عملیات در کلاس ها) ،مهمترین سئوال این است که با چه هدفی دنبال می شود.بسته به نوع هدف،#C و NET. امکانات متفاوتی رو در اختیار می گذارند.برای نمونه ،چند وقت قبل برنامه ای داشتم که باید اطلاعات یک فایل باینری نوشته شده توسط VC6 رو در VC.NEt بارگذاری می کردم.این اطلاعات در VC6 با کلاس ها به راحتی قابل خواندم و نوشتن هستند ولی در .NET باید همه چیز را کنترل می کردیم.به همین منظور از کلاس Marshal در System::Runtime::InteropServices استفاده کردم.

موفق باشید