گفتگو هایی در باب سی شارپ

the_king

مدیرکل انجمن
ممنون استاد علی :rose: راستی ، عیدتون مبارک باشه:rose:
پس کلا با همین کلاس ManualResetEvent که کار کنیم برای استوپ و مکث و ادامه دادن نخ ها ، همین قضیه ی توقف ناگهانی رو خودش اتوماتیک مدیریت میکنه دیگه؟ درسته؟
هر چند من که یه کمی با اون توابعی که داخل Thread بود که کار کردم ، مشکلی ندیدم داشته باشه (هر چند پیشنهاد خود مایکروسافت اینه که استفاده نکنیم)
خیلی کم پیش میاد که لازم باشه نخی متوقف بشه، به همون دلیل که در کمترین برنامه ای وسط کار دکمه pause می بینید. cancel و abort زیاد هست ولی pause کاربردش خیلی کمه. کارکرد ManualResetEvent هم به همون نسبت کمه. بیشترین موارد lock کردن ها است، اینکه برای انجام کاری چند لحظه معطل بشه که منبعی آزاد بشه.
اغلب کارهایی که در برنامه های عادی #C انجام میشه نیازمند BackgroundWorker ئه که کارکرد مشخص و ساده ای داره.
اون قضیه هم که میگید مشکلی ندیدم نمیدونم ملاک تون چیه، ممکنه ده تا لگد بزنیم به کیس کامپیوتر و بگیم بررسی کردیم و با لگد زدن به کیس مشکلی پیش نمیاد.


همین کدی که دادم ، چجوری هه قضیه اش؟ یعنی باید چجوری تغییر بدم تا ارور نده؟
قسمت return رو همین طور که گفتین تغییر دادم ولی بازم ارور میده!
من اصلا متوجه نمیشم شما چی دارید می نویسید، یه چیزی که منطق درستی نداره. شما از این Generic چه توقعی دارید؟ (where new(char[] ab تعریفی نیست که بخواهید ازش استفاده کنید، کجا شبیه به این رو دیدید؟ اون ab از کجا قراره مقدارش بیاد که حالا در return ازش استفاده بکنید؟ اول برای خودتون مشخص کنید که قراره Generic چه چیزی رو بر اساس چه چیزی ایجاد کنه، بعد بیایید به پیاده سازیش فکر کنید.
 

SU-57

Active Member
آقا سجاد شما در جایی از فیلم گفتی برنامه نویسی یعنی ریاضی. ولی من به جز 4 عمل ریاضی و یکسری نمادها مثل پرانتز چیز دیگه ای ندیدم وشاید در قسمت های دیگه اونا رو بفهمم.
سوالم اینه که چه مباحثی از ریاضی مهمه که یاد بگیریم تا یک برنامه نویس حرفه ای بشیم چون ریاضی من ضعیفه برم یه چند تا کتاب بخرم تمرین کنم یه مقدار پایم قوی بشه
اگه استاد علی هم لطف کنن پاسخ بدن ممنون میشم
 

the_king

مدیرکل انجمن
آقا سجاد شما در جایی از فیلم گفتی برنامه نویسی یعنی ریاضی. ولی من به جز 4 عمل ریاضی و یکسری نمادها مثل پرانتز چیز دیگه ای ندیدم وشاید در قسمت های دیگه اونا رو بفهمم.
سوالم اینه که چه مباحثی از ریاضی مهمه که یاد بگیریم تا یک برنامه نویس حرفه ای بشیم چون ریاضی من ضعیفه برم یه چند تا کتاب بخرم تمرین کنم یه مقدار پایم قوی بشه
اگه استاد علی هم لطف کنن پاسخ بدن ممنون میشم
من همچین نظری ندارم، شما ریاضیدان برجسته ای هم باشید الزامی نیست که دانش ریاضی در برنامه نویسی کمک تون کنه.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
آقا سجاد شما در جایی از فیلم گفتی برنامه نویسی یعنی ریاضی. ولی من به جز 4 عمل ریاضی و یکسری نمادها مثل پرانتز چیز دیگه ای ندیدم وشاید در قسمت های دیگه اونا رو بفهمم.
سوالم اینه که چه مباحثی از ریاضی مهمه که یاد بگیریم تا یک برنامه نویس حرفه ای بشیم چون ریاضی من ضعیفه برم یه چند تا کتاب بخرم تمرین کنم یه مقدار پایم قوی بشه
اگه استاد علی هم لطف کنن پاسخ بدن ممنون میشم

بله
به نظر من ، مهم ترین قسمت برنامه نویسی که الگوریتم برنامه هست ، یعنی تبدیل زبان خودمون به زبان ریاضی
ریاضی رو میشه به چند بخش تقسیم کرد . پایه ی همه برنامه نویسی ها (و کلا کامپیوتر) که ریاضی گسسته هست (و تا جایی که لازم بود و بلد بودم ، مباحث اولیه ی ریاضی گسسته یعنی همون قضیه ی اعداد دودویی و ... در آموزش گفته شد) . کلا هر چی ریاضی گسسته ی آدم خوب باشه ، ارتباطش با کامپیوتر راحت تره .
بخش دیگه که نوشتن الگوریتم هست ، بسته به این داره که چه برنامه ای نوشته شه و به نسبت اون برنامه ، اهمیت ریاضی (ریاضی عادی) در نوشتن برنامه کم رنگ و پر رنگ میشه . مثلا شما اگه در برنامه نویسی ، با گرافیک (رسم خط و نقطه و ...) کار کنین (آموزش ها هنوز به قسمت گرافیک نرسید) ، بسته به نوع کارتون و پیچیدگی اش ، با ریاضی و حتی هندسه ، سر و کار دارین . فرضا اگه بخواین با رسم نقطه های پی در پی ، یک خط رسم کنین ، قطعا باید معادله ی خط در ریاضی رو بلد باشین (حالا این نمونه ی بسیار ساده اش بود) . حتی با رسم اشکال مختلف ، قوانین هندسه هم لازم میشه . یا اگه بازی بسازین ، چون اشیاء مثل دنیای واقعی روابط فیزیکی دارن در بازی (مثلا با برخورد دو جسم ، اتفاقات مختلفی میافته) ، حتی معادلات فیزیک هم لازم میشه
کلا بستگی داره که چه برنامه ای بنویسین تا قدرت ریاضی در برنامه نویسی ظهور کمتر یا بیشتری پیدا کنه
درس هایی که در برنامه نویسی تاثیر میذارن ، ریاضی گسسته و بعد بسته به نوع الگوریتم و حرفه ای بودن بنامه تون ، ریاضیات معمولی ، هندسه و حتی درس طراحی الگوریتم تاثیر داره
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
سلام
استاد علی ، من هنوز متوجه نشدم که چرا توی متد سازنده ی استراکچرها ، مقداردهی فیلدها و پروپرتی ها اجباری هه؟!!
هم در کلاس و هم در استراکچرها ، وقتی یک فیلدی از نوع کلاس رو مینویسیم ، مقدار پیش فرض هر دو ، null هست . یعنی اگه قرار باشه مقداردهی در متد سازنده ی استراکچرها ، اجباری باشه (که دلیل شو نمیدونم) ، قطعا توی متد سازنده ی پیش فرض استراکچرها (اون متد سازنده ای که هیچ ورودی ای نمیگیره) ، مقداردهی نمیشن و مقدارشون همون مقدار پیش فرض متغییر سراسری (کلاس که null میشن) هست
 

the_king

مدیرکل انجمن
سلام
استاد علی ، من هنوز متوجه نشدم که چرا توی متد سازنده ی استراکچرها ، مقداردهی فیلدها و پروپرتی ها اجباری هه؟!!
هم در کلاس و هم در استراکچرها ، وقتی یک فیلدی از نوع کلاس رو مینویسیم ، مقدار پیش فرض هر دو ، null هست . یعنی اگه قرار باشه مقداردهی در متد سازنده ی استراکچرها ، اجباری باشه (که دلیل شو نمیدونم) ، قطعا توی متد سازنده ی پیش فرض استراکچرها (اون متد سازنده ای که هیچ ورودی ای نمیگیره) ، مقداردهی نمیشن و مقدارشون همون مقدار پیش فرض متغییر سراسری (کلاس که null میشن) هست
ساختار حافظه struct که دوبار با دو تا متد سازنده متفاوت مقدار دهی نمیشه، یک متد سازنده قراره اجرا بشه. وقتی قراره با متد سازنده ای مقدار دهی بشه که پارامتر داره دیگه متد سازنده بدون پارامتر دخالتی نداره. متد سازنده struct هم که بجز مقدار دهی اولیه فیلد ها که کار دیگه ای نداره که بگیم مقدار دهی فیلد ها اختیاری باشه. مثل قضیه مقدار دهی متغیر های محلی ئه.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
ساختار حافظه struct که دوبار با دو تا متد سازنده متفاوت مقدار دهی نمیشه، یک متد سازنده قراره اجرا بشه. وقتی قراره با متد سازنده ای مقدار دهی بشه که پارامتر داره دیگه متد سازنده بدون پارامتر دخالتی نداره. متد سازنده struct هم که بجز مقدار دهی اولیه فیلد ها که کار دیگه ای نداره که بگیم مقدار دهی فیلد ها اختیاری باشه. مثل قضیه مقدار دهی متغیر های محلی ئه.

ممنون
ولی دقیق سئوال مو متوجه نشدین
میدونم وظیفه ی متد سازنده ، مقداردهی فیلدها و پروپرتی ها هستن ولی خوب وظیفه ی متد سازنده در کلاس ها هم همینه دیگه . پس چرا مقداردهی فیلدها و پروپرتی ها در متد سازنده در کلاس ها ، اختیاری هه ولی در استراکچرها اجباری؟!


وراثت از یه Value Type با توجه به ساختارش عملی نیست. Value Type ها صرفا یک فضای حافظه دارند، ارجاعی در کار نیست. قراره همینطور کلی از یک متغیر مقادیر کپی بشن در یک متغیر دیگه. اگه قراره Point باشه، صرفا باید حافظه اش اندازه یک Point باشه و دقیقا مطابق با ساختار یک Point. بدون کوچکترین تغییر. اگه در وارثش ساختار یک تغییر کوچیک بکنه دیگه نمیشه مثل Value Type ها کپی بشه. وراثت ساختار حافظه شو تغییر میده. اگه بخواهید مثلا کلاس ها که در وراثت انواع تغییرات و override و new کردن و ... دارند باهاشون رفتار کنید دیگه نمیشه با این شیوه مقدارشون رو کپی کرد.

اینو در صفحه ی قبل گفتین
چرا با override کردن ( و new کردن و ...) ، مقدارها (مقدار یک متغییر در متغییر دیگه) کپی نمیشه؟ مشکلش چیه؟
---------------------
سوم اینکه چرا در استراکچرها نمیشه به فیلدها و پروپرتی ها مقدار اولیه داد؟
 

SU-57

Active Member
چرا این ToString() که حتما باید پرانتز باز و بسته آخرش بیاد به طور اتوماتیک توسط ویژوال اضافه نمی شه و باید دستی این کار رو انجام بدیم؟
 
آخرین ویرایش:

the_king

مدیرکل انجمن
ممنون
ولی دقیق سئوال مو متوجه نشدین
میدونم وظیفه ی متد سازنده ، مقداردهی فیلدها و پروپرتی ها هستن ولی خوب وظیفه ی متد سازنده در کلاس ها هم همینه دیگه . پس چرا مقداردهی فیلدها و پروپرتی ها در متد سازنده در کلاس ها ، اختیاری هه ولی در استراکچرها اجباری؟!
بخاطر اینکه در struct ها مقدار پیشفرض رو متد سازنده بدون پارامتر تعیین می کنه،نه اینکه ذاتا مقدار پیشفرض داشته باشند. وقتی متد سازنده با پارامتریی اجرا بشه دیگه متد سازنده بدون پارامتر اجرا نمیشه که مقدار پیشفرض بده. متغیر باید مقدار داشته باشه، چه مقدار null و یا هر مقدار دیگه ای.

اینو در صفحه ی قبل گفتین
چرا با override کردن ( و new کردن و ...) ، مقدارها (مقدار یک متغییر در متغییر دیگه) کپی نمیشه؟ مشکلش چیه؟
فرض کنید که یک متغیر int دارید به نام i ، این متغیر i نه اشاره گر ئه و نه طول حافظه اش تغییری می کنه و نوع داده داخلش رو جایی ثبت می کنه، همواره یک مقدار int با طول مشخص int رو نگهداری می کنه و طولش حافظه اش هم برابر با طول حافظه int ئه. حالا در این متغیر i می توانید حافظه یک float یا long رو جای بدید؟ نمیشه. طول حافظه شون هم برابر باشه مشخصاتشون یکی نیست، باز ناسازگارند. struct ها هم همینطور ئه. وقتی متغیر x رو از نوع یک struct تعریف می کنید یک متغیر اشاره گر نیست، حافظه ای داره به اندازه حافظه اون struct و دقیقا منطبق بر اون struct ئه. شما اگه می توانستید از struct ئه وارثی داشته باشید یا طول حافظه اش تغییر می کرد و یا اگه طول حافظه وارثش تغییر نمی کرد لااقل مشخصاتش متفاوت بود. یا نمی توانستید در اون حافظه متغیر x یک حافظه از نوع وارث رو قرار بدید و یا اگه قرار میدادید مشخصاتش با x سازگار نبود.

سوم اینکه چرا در استراکچرها نمیشه به فیلدها و پروپرتی ها مقدار اولیه داد؟
زمانی که مقدار اولیه باید داده بشه مطرحه، نه اینکه نشه مقدار اولیه داد. شما struct رو کی ایجاد می کنید؟ اون زمانه که باید مقدار اولیه داده بشه. وقتی هنوز ازش نمونه ساخته نشده مقدار اولیه نمیشه داد. جایی جلوی مقدار دهی رو میگیره که موقع تعریف شدنش ئه، موقع تعریف کردن فیلد یا پروپرتی میخواهید بهش مقدار اولیه بدهید؟ در اون زمان عملی نیست.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
چرا این ToString() که حتما باید پرانتز باز و بسته آخرش بیاد به طور اتوماتیک توسط ویژوال اضافه نمی شه و باید دستی این کار رو انجام بدیم؟

ToString() متد (تابع) هه .
هر تابعی یک کاری رو انجام میده . ویژال استودیو نمیدونه چه زمانی شما نیاز به تبدیل به رشته دارین که بخواد خودش اتوماتیک به رشته تبدیل کنه (این حداقل دلیلی هست که میشه براش گفت)
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
بخاطر اینکه در struct ها مقدار پیشفرض رو متد سازنده بدون پارامتر تعیین می کنه،نه اینکه ذاتا مقدار پیشفرض داشته باشند. وقتی متد سازنده با پارامتریی اجرا بشه دیگه متد سازنده بدون پارامتر اجرا نمیشه که مقدار پیشفرض بده. متغیر باید مقدار داشته باشه، چه مقدار null و یا هر مقدار دیگه ای.
ممنون استاد علی
من الان قشنگ توجه نشدم
متد سازنده ی پیش فرض که انگار مقداری رو تعیین نمیکنه! وقتی متد سازنده ی پیش فرض استراکچر اجرا میشه ، مقدار اعضای استراکچرها (مثل فیلد و پروپرتی و ...) ، همون پیش فرض (مثلا اعداد صفر و ...) هست و مقدار انواع کلاس ها هم null هست . این مقادیر هم که اصلا وقتی متغییرهای سراسری و کلا اعضای سراسری تعریف میشن ، با خودشون این مقادیر رو دارن



فرض کنید که یک متغیر int دارید به نام i ، این متغیر i نه اشاره گر ئه و نه طول حافظه اش تغییری می کنه و نوع داده داخلش رو جایی ثبت می کنه، همواره یک مقدار int با طول مشخص int رو نگهداری می کنه و طولش حافظه اش هم برابر با طول حافظه int ئه. حالا در این متغیر i می توانید حافظه یک float یا long رو جای بدید؟ نمیشه. طول حافظه شون هم برابر باشه مشخصاتشون یکی نیست، باز ناسازگارند. struct ها هم همینطور ئه. وقتی متغیر x رو از نوع یک struct تعریف می کنید یک متغیر اشاره گر نیست، حافظه ای داره به اندازه حافظه اون struct و دقیقا منطبق بر اون struct ئه. شما اگه می توانستید از struct ئه وارثی داشته باشید یا طول حافظه اش تغییر می کرد و یا اگه طول حافظه وارثش تغییر نمی کرد لااقل مشخصاتش متفاوت بود. یا نمی توانستید در اون حافظه متغیر x یک حافظه از نوع وارث رو قرار بدید و یا اگه قرار میدادید مشخصاتش با x سازگار نبود.


زمانی که مقدار اولیه باید داده بشه مطرحه، نه اینکه نشه مقدار اولیه داد. شما struct رو کی ایجاد می کنید؟ اون زمانه که باید مقدار اولیه داده بشه. وقتی هنوز ازش نمونه ساخته نشده مقدار اولیه نمیشه داد. جایی جلوی مقدار دهی رو میگیره که موقع تعریف شدنش ئه، موقع تعریف کردن فیلد یا پروپرتی میخواهید بهش مقدار اولیه بدهید؟ در اون زمان عملی نیست.

آها ممنون متوجه شدم
فقط سئوال سوم که پرسیده بودم " سوم اینکه چرا در استراکچرها نمیشه به فیلدها و پروپرتی ها مقدار اولیه داد؟ " رو ممنون میشم جواب بدین
ممنون

:rose:
 

the_king

مدیرکل انجمن
ممنون استاد علی
من الان قشنگ توجه نشدم
متد سازنده ی پیش فرض که انگار مقداری رو تعیین نمیکنه! وقتی متد سازنده ی پیش فرض استراکچر اجرا میشه ، مقدار اعضای استراکچرها (مثل فیلد و پروپرتی و ...) ، همون پیش فرض (مثلا اعداد صفر و ...) هست و مقدار انواع کلاس ها هم null هست . این مقادیر هم که اصلا وقتی متغییرهای سراسری و کلا اعضای سراسری تعریف میشن ، با خودشون این مقادیر رو دارن
همچین چیزی که میگید فرض اولیه نادرستی داره. شما اول فرض رو بر این میگیرید که عملکرد متد سازنده بدون پارامتر struct و شیوه مقدار دهی اولیه در struct ها رو می دانید، بعد ایراد میگیرید که چرا در عمل مطابق برداشت تون نیست. قبلا هم گفتم، شیوه تحقیق تجربی برای مباحث کامپیوتری و نرم افزاری مناسب نیست. قواعد و اصول زبان رو با این شیوه نمیشه استخراج کرد. قواعد و اصول زبان رو نمی توانید از روی تجربیات تون استخراج کنید. همانطور که نحوه مقدار دهی اولیه فیلد های سراسری در کلاس ها رو نمیشد به متغیر های محلی داخل متد تعمیم داد، شیوه مقدار دهی اولیه فیلد های سراسری در کلاس ها رو نمیشه به struct ها تعمیم داد.


آها ممنون متوجه شدم
فقط سئوال سوم که پرسیده بودم " سوم اینکه چرا در استراکچرها نمیشه به فیلدها و پروپرتی ها مقدار اولیه داد؟ " رو ممنون میشم جواب بدین
ممنون

:rose:
پاسخ داده بودم. پاسخ ویرایش شده ام را نخواندید.
چرا این ToString() که حتما باید پرانتز باز و بسته آخرش بیاد به طور اتوماتیک توسط ویژوال اضافه نمی شه و باید دستی این کار رو انجام بدیم؟
بخاطر اینه که بدون () هم در زبان معنی و کاربرد داره. ToString متد ئه و ()ToString فراخوانی اونه. درسته که دومی استفاده به مراتب بیشتری داره ولی هر دوشون معنی داره و اولی هم در مواردی کاربرد داره.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
ممنون
آها
پس کارکرد و مقداردهی (فیلد و پروپرتی ها) در کلاس و استراکچر با هم فرق دارن؟ پس بصورت پیش فرض ، برخلاف کلاس ها ، وقتی فیلد و پروپرتی رو بصورت سراسری در استراکچر تعریف میکنیم ، مقدار پیش فرض ندارن؟ درسته؟ دلیل اش هم قطعا باید برگرده به value type یودن استراکچرها ؟ درسته؟ اما این قضیه ، دقیقا چجوری و چطور به value type بودن ارتباط داره رو نمیدونم
------------
چرا استراکچرها نمیتونن از هیچ کلاسی ارث بری کنن (البته مشخص هست که sealed هستن) ولی از همه شون میتونن از کلاس System.ValueType ارث بری کنن و مهمتر اینکه چرا میتونن از اینترفیس ها ارث بری کنن؟
----------
کلا استراکچرها خیلی نکات داره . نکات داشتن مهم نیست . چیزی که سختمه اینه که دلیل این نکات و محدودیت ها رو یا نمیدونم یا به سختی درک میکنم . به نظرم برنامه نویسی وقتی که دلیل محدودیت ها و نکات دونسته بشه ، خیلی یادگیری اش آسون تر میشه وگرنه آدم حفظ میکنه (مثل فیزیک برای من :green:) که سریع هم برنامه نویسی رو فراموش میکنه
ای کاش آموزش برنامه نویسی رو یکی مثل شما میداد که به همه ی این دلیل ها و کلا برنامه نویسی مسلط این تا مزه ی واقعی برنامه نویسی رو همه درک کنن . البته من هم تا اینجا ، تا تونستم ، دلیل مسائل رو گفتم ولی دیگه خیلی دلیل محدودیت هایی که مباحث استراکچر و جنریک ها و constraint هاشون و اینترفیس ها ایجاد میکنن ، رو نمیدونم و بهشون تسلط کامل ندارم
درد دل کردم
:green:
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
آها چون همه ی استراکچرها از کلاس System.ValueType ارث بری میکنن (و نمیشه ارث بری نکنن) و بنابراین یه استراکچر یا کلاس ، نمیتونه همزمان از یک کلاس یا استراکچر دیگه هم ارث بری کنه ، بنابراین استراکچرها نمیتونن از کلاس دیگه ای ارث بری کنن ولی مثل کلاس ها ، از اینترفیس ها میشه ارث بری کرد . درسته؟
 

the_king

مدیرکل انجمن
ممنون
آها
پس کارکرد و مقداردهی (فیلد و پروپرتی ها) در کلاس و استراکچر با هم فرق دارن؟ پس بصورت پیش فرض ، برخلاف کلاس ها ، وقتی فیلد و پروپرتی رو بصورت سراسری در استراکچر تعریف میکنیم ، مقدار پیش فرض ندارن؟ درسته؟ دلیل اش هم قطعا باید برگرده به value type یودن استراکچرها ؟ درسته؟ اما این قضیه ، دقیقا چجوری و چطور به value type بودن ارتباط داره رو نمیدونم
ربطش اینه که صرفا یک حافظه بهش تخصیص داده شده، از همون لحظه تعریف شدن. مثلا 100 بایت. باید داخل این حافظه مقدار قرار بگیره تا معتبر باشه و قابل استفاده باشه، حتی اگه مقادیر پیشفرض اون نوع های داده هم باشه باید در اون حافظه ثبت بشه. مثلا تاریخ مقدار پیشفرض داره، اما این مقدار پیشفرض باید اول در حافظه ثبت بشه، یک حافظه با مقادیر نامشخص که معتبر نیست. در مورد reference type ها این مورد مربوط به زمان ایجاد شدن شیء بود، چون متغیر های مربوطه که حافظه ای برای داده شیء ندارن، متغیر ها صرفا یک اشاره گر هستند و در لحظه تعریف شدن متغیر هم خبری از حافظه برای شیء نیست.

چرا استراکچرها نمیتونن از هیچ کلاسی ارث بری کنن (البته مشخص هست که sealed هستن) ولی از همه شون میتونن از کلاس System.ValueType ارث بری کنن و مهمتر اینکه چرا میتونن از اینترفیس ها ارث بری کنن؟

به نظرتون چه معنی ای داره استراکچر ای که از یک کلاس ارث بری کنه؟ بالاخره یا باید Reference Type باشه یا Value Type، دو تاش که نمیشه. ValueType یک مورد داخل زبان ئه، همانطور که null ئه مقداریه که Type نداره. مثل ها Attribute که در ویژوال استدیو میشه خود Attribute شون رو ننوشت و بجای FlagsAttribute بنویسیم Flags. همانطور که Attribute یک کلاس ئه مثل سایر کلاس ها اما در ویژوال استدیو نقش اش ویژه است و با خصوصیات ویژه. اگه ValueType وجود نداشت، گروه بندی شون و فراخوانی با امکانات System.Reflection با مشکل مواجه میشد. کلا وقتی لازم باشه کل یک مجموعه از قواعد مشترکی تبعیت کنه مجبور هستیم که یکسری موارد استثنایی داشته باشیم.

از Interface ارث بری نمیشه، Interface پیاده سازی میشه، با هم فرق داره. دو تا مورد که یک Interface یکسان رو پیاده سازی می کنن یک متد هایی رو الزامی دارند، اما به این معنی نیست که مشترکا وارث چیزی باشند. پیاده سازی یک یا چند Interface ایرادی برای struct ایجاد می کنه؟ نه، فقط وادارش میکنه یک متد هایی رو داشته باشه. ربطی به حافظه اش هم نداره.

آها چون همه ی استراکچرها از کلاس System.ValueType ارث بری میکنن (و نمیشه ارث بری نکنن) و بنابراین یه استراکچر یا کلاس ، نمیتونه همزمان از یک کلاس یا استراکچر دیگه هم ارث بری کنه ، بنابراین استراکچرها نمیتونن از کلاس دیگه ای ارث بری کنن ولی مثل کلاس ها ، از اینترفیس ها میشه ارث بری کرد . درسته؟
چیزی که میگید دلیل موجهی نیست. اگه دلیل این باشه پس می توانید خودتون یک کلاس وارث از System.ValueType بسازید و struct تون رو وارث اون کلاس دست ساز بکنید که عملی نیست.
قواعد زبان رو با استقراء و قیاس استخراج نکنید، اینها مباحث ریاضی یا فلسفی نیستند. نتایجی که میگیرید هم قابل اتکا نیستند. چون دست ها پنج انگشت دارن، باید پاها پنج انگشت داشته باشند. یا چون گوش دو تا است و نمیشه باهاش غذا خورد، پس با چشم هم نمیشه غذا خورد چون دو تا است، اما با دهن میشه غذا خورد چون دو تا نیست. جور در اومدن اینجور استدلال ها کمکی نمی کنه.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
ممنون
استاد علی ، چرا در کد زیر ، موقع فراخونی و استفاده از استراکچر (بدون استفاده از new) ، هیچ اروری نمیده :

کد:
    struct Gamepad
    {
        public string name;
        public string color;

        public Gamepad(string name, string color)
        {
            this.name = name;
            this.color = color;
        }

        public void Show()
        {
            Console.WriteLine("Name : " + name);
            Console.WriteLine("Color: " + color);
        }
    }

و درون رویدادی در فرم1 :

کد:
            Gamepad gamepad3; // no constructor
            gamepad3.name = "Steam Controller";
            gamepad3.color = "Gray";
            gamepad3.Show();

اما همین مدل در کد زیر ارور Use of unassigned local variable 'bdk' رو میده؟!!! :

کد:
        public struct TestStruct
        {
            public int X { get; set; };     
            public int Y { get; set; }
            public Button Btn { get; set; }
            public StringBuilder StrBld;
            public static int StaticInitialize = 100;
            public TestStruct(string str)
            {
                this.X = 10;  
                this.Y = 20;
                this.Btn = new Button();
                this.StrBld = new StringBuilder(str);
            }
        }

و در رویدادی در فرم1 :

کد:
            MyClasses.TestStruct bdk;
            bdk.Btn = new Button();
            bdk.X = 10;
            bdk.Y = 4;
            bdk.StrBld = new StringBuilder("d");
            MyClasses.TestStruct.StaticInitialize = 1;

حتی متد استاتیکش رو هم مقداردهی کردم!
 

the_king

مدیرکل انجمن
ممنون
استاد علی ، چرا در کد زیر ، موقع فراخونی و استفاده از استراکچر (بدون استفاده از new) ، هیچ اروری نمیده :

کد:
    struct Gamepad
    {
        public string name;
        public string color;

        public Gamepad(string name, string color)
        {
            this.name = name;
            this.color = color;
        }

        public void Show()
        {
            Console.WriteLine("Name : " + name);
            Console.WriteLine("Color: " + color);
        }
    }

و درون رویدادی در فرم1 :

کد:
            Gamepad gamepad3; // no constructor
            gamepad3.name = "Steam Controller";
            gamepad3.color = "Gray";
            gamepad3.Show();

اما همین مدل در کد زیر ارور Use of unassigned local variable 'bdk' رو میده؟!!! :

کد:
        public struct TestStruct
        {
            public int X { get; set; };    
            public int Y { get; set; }
            public Button Btn { get; set; }
            public StringBuilder StrBld;
            public static int StaticInitialize = 100;
            public TestStruct(string str)
            {
                this.X = 10; 
                this.Y = 20;
                this.Btn = new Button();
                this.StrBld = new StringBuilder(str);
            }
        }

و در رویدادی در فرم1 :

کد:
            MyClasses.TestStruct bdk;
            bdk.Btn = new Button();
            bdk.X = 10;
            bdk.Y = 4;
            bdk.StrBld = new StringBuilder("d");
            MyClasses.TestStruct.StaticInitialize = 1;

حتی متد استاتیکش رو هم مقداردهی کردم!
بخاطر Auto Property ئه Btn تونه، شما یه پروپرتی تعریف کردید که به هیچ متغیر در دسترسی وابسته نیست و مقدار دهی اولیه اش با خودتونه، سازنده بدون پارامتر struct نمیتونه برای این Auto Property ها مقدار دهی اولیه بکنه چون متغیری برای مقدار دهی نداره. خود مایکروسافت توصیه می کنه که از Auto Property ها در struct استفاده نکنید :
Auto-implemented properties should be avoided in structs because they have no backing field and therefore cannot be initialized in any way from the constructor.
Compiler Error CS0188
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
بخاطر Auto Property ئه Btn تونه، شما یه پروپرتی تعریف کردید که به هیچ متغیر در دسترسی وابسته نیست و مقدار دهی اولیه اش با خودتونه، سازنده بدون پارامتر struct نمیتونه برای این Auto Property ها مقدار دهی اولیه بکنه چون متغیری برای مقدار دهی نداره. خود مایکروسافت توصیه می کنه که از Auto Property ها در struct استفاده نکنید :

Compiler Error CS0188

ممنون
کد رو به شکل زیر تغییر دادم و x و y رو حذف و button رو هم به پروپرتی معمولی تغییر دادم ولی بازم همون ارور رو میده!! :

کد:
        public struct TestStruct
        {
            //public int X { get; set; }
            //public int Y { get; set; }
            private Button _btn;
            public Button Btn
            {
                get
                {
                    return this._btn;
                }
                set
                {
                    this._btn = value;
                }
            }
            public StringBuilder StrBld;
            public static int StaticInitialize = 100;
            public TestStruct(string str)
            {
              
                //this.X = 10;
                //this.Y = 20;
                this._btn = new Button();
                this.StrBld = new StringBuilder(str);
            }
        }

و در رویدادی :

کد:
MyClasses.TestStruct b;
            b.Btn = new Button();
            b.StrBld = new StringBuilder("d");
 

the_king

مدیرکل انجمن
ممنون
کد رو به شکل زیر تغییر دادم و x و y رو حذف و button رو هم به پروپرتی معمولی تغییر دادم ولی بازم همون ارور رو میده!! :

کد:
        public struct TestStruct
        {
            //public int X { get; set; }
            //public int Y { get; set; }
            private Button _btn;
            public Button Btn
            {
                get
                {
                    return this._btn;
                }
                set
                {
                    this._btn = value;
                }
            }
            public StringBuilder StrBld;
            public static int StaticInitialize = 100;
            public TestStruct(string str)
            {
            
                //this.X = 10;
                //this.Y = 20;
                this._btn = new Button();
                this.StrBld = new StringBuilder(str);
            }
        }

و در رویدادی :

کد:
MyClasses.TestStruct b;
            b.Btn = new Button();
            b.StrBld = new StringBuilder("d");
خطا مشابهه اما الان مساله یه چیز دیگه است، الانم error میده چون میگه از یک پروپرتی (یا متد) استفاده کرده اید، پیش از اینکه همه فیلد ها صریحا مقدار دهی بشوند. یک مثال ساده براتون بزنم :
کد:
        public struct AAAA
        {
            public int x;

            public void M()
            {
            }
        }

            AAAA a;
            a.M();
اینجا مشکل این نیست که x مقدار پیشفرض نداره، اصلا M کاری هم به x نداره، اما کامپایلر میگه اول x و هر فیلد دیگه ای که struct داره رو مقدار دهی اش کن بعد برو سر فراخوانی M
اهمیتی هم نمیده که اون x به هر حال مقدار پیشفرض 0 رو داره. با همون منطق که میگه متغیر محلی حافظه داره، متغیر ها هم مقدار پیشفرض دارند، ولی بازم تا مقدار دهی اش نکنی نمیذارم ازش مقدار بخونی :
کد:
        public struct AAAA
        {
            public int x;

            public void M()
            {
            }
        }

            AAAA a;
            a.x = 0;
            a.M();
اون سطر ;a.x = 0 هیچ تاثیری روی کارکرد M نداشت ولی کامپایلر رو مطمئن می کنه که پیش از فراخوانی M شما همه مقادیر فیلد ها رو خودتون صریحا مشخص کرده اید.
راه حل ساده و اصولی اش اینه که خودتون متد سازنده بدون پارامتر یا با پارامتر رو فراخوانی کنید. چرا؟ چون وقتی شما یک new struct رو در متغیر کپی می کنید یک struct آماده و با همه متغیر های مقدار دهی شده رو کپی می کنه در حافظه متغیر تون. دیگه از این به بعد کامپایلر نمیتونه ایراد بگیره که متغیری مقدار دهی نشده، همه شون مقدار پیشفرض رو دارند. دقت کنید که new struct فراخوانی متد سازنده در یک struct دیگه است که حافظه اش کپی میشه در متغیر مورد نظر شما. این به این معنی نیست که اگه این کار رو نمی کردید فیلد ها مقدار پیشفرض نداشتند، مقدار پیشفرض رو دارند، ولی متد سازنده بدون پارامتر یا با پارامتری رو فراخوانی نکرده اید، کامپایلر اصرار داره که قبل از فراخوانی پروپرتی و متد ها، صریحا مقادیر تمامی فیلد ها رو به یک شیوه ای تعیین کنید. یکی از روش های تعیین مقادیر اجرا کردن متد سازنده بدون پارامتر ئه.
کد:
  TestStruct b = new TestStruct();
  b.Btn = new Button();
  b.StrBld = new StringBuilder("d");
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
خطا مشابهه اما الان مساله یه چیز دیگه است، الانم error میده چون میگه از یک پروپرتی (یا متد) استفاده کرده اید، پیش از اینکه همه فیلد ها صریحا مقدار دهی بشوند. یک مثال ساده براتون بزنم :
کد:
        public struct AAAA
        {
            public int x;

            public void M()
            {
            }
        }

            AAAA a;
            a.M();
اینجا مشکل این نیست که x مقدار پیشفرض نداره، اصلا M کاری هم به x نداره، اما کامپایلر میگه اول x و هر فیلد دیگه ای که struct داره رو مقدار دهی اش کن بعد برو سر فراخوانی M
اهمیتی هم نمیده که اون x به هر حال مقدار پیشفرض 0 رو داره. با همون منطق که میگه متغیر محلی حافظه داره، متغیر ها هم مقدار پیشفرض دارند، ولی بازم تا مقدار دهی اش نکنی نمیذارم ازش مقدار بخونی :
کد:
        public struct AAAA
        {
            public int x;

            public void M()
            {
            }
        }

            AAAA a;
            a.x = 0;
            a.M();
اون سطر ;a.x = 0 هیچ تاثیری روی کارکرد M نداشت ولی کامپایلر رو مطمئن می کنه که پیش از فراخوانی M شما همه مقادیر فیلد ها رو خودتون صریحا مشخص کرده اید.
راه حل ساده و اصولی اش اینه که خودتون متد سازنده بدون پارامتر یا با پارامتر رو فراخوانی کنید. چرا؟ چون وقتی شما یک new struct رو در متغیر کپی می کنید یک struct آماده و با همه متغیر های مقدار دهی شده رو کپی می کنه در حافظه متغیر تون. دیگه از این به بعد کامپایلر نمیتونه ایراد بگیره که متغیری مقدار دهی نشده، همه شون مقدار پیشفرض رو دارند. دقت کنید که new struct فراخوانی متد سازنده در یک struct دیگه است که حافظه اش کپی میشه در متغیر مورد نظر شما. این به این معنی نیست که اگه این کار رو نمی کردید فیلد ها مقدار پیشفرض نداشتند، مقدار پیشفرض رو دارند، ولی متد سازنده بدون پارامتر یا با پارامتری رو فراخوانی نکرده اید، کامپایلر اصرار داره که قبل از فراخوانی پروپرتی و متد ها، صریحا مقادیر تمامی فیلد ها رو به یک شیوه ای تعیین کنید. یکی از روش های تعیین مقادیر اجرا کردن متد سازنده بدون پارامتر ئه.
کد:
  TestStruct b = new TestStruct();
  b.Btn = new Button();
  b.StrBld = new StringBuilder("d");

ممنون
نه
همون ارور هه
Use of unassigned local variable 'b'
اون x و y رو کامنت کردم . یعنی حذف شدن و وجود ندارن
عکس رو پیوست کردم

0.JPG
 

جدیدترین ارسال ها

بالا