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

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
سلام استاد علی
آقا ، در لینک زیر ، گفت توی C# 7 که توی ویژال استودیو 2017 هست ، این قابلیت اضافه شد که بدون استفاده از کلمه کلیدی out ، چندین مقدار رو برگردوند :
K. G. Sreeju - C# 7 - Return multiple values from methods

ولی من مثل اون ، تابع مو تعریف میکنم ، ارور میده . تابع رو این جوری تعریف میکنم :


کد:
public (int, int) MyMethod11()
        {
            return (10, 20);
        }

متن ارور اینه :
Error CS8179 Predefined type 'System.ValueTuple`2' is not defined or imported
نسخه ی دات نت ام ، 4.6.2 هست .
دلیل اش چیه؟ بخاطر نسخه ی دات نت ام هست؟

ویرایش : ممنون . جوابشو پیدا کردم . طبق راهنمای این لینک :
Predefined type 'System.ValueTuple´2´ is not defined or imported
بخاطر نسخه ی 4.6.2 هست .که دستور زیر رو در NuGet زدم ، درست شد :
Install-Package "System.ValueTuple"
یا باید دات نت 4.7 باشه

---------------------
بعد اینکه ، تیوپل چیه؟
طبق مقاله ی زیر :
آشنایی با قابلیت های جدید سی شارپ 7.0
این کد رو تعریف کردم :

کد:
(int, string) a = (5, "salam");
            MessageBox.Show(a.Item2.ToString());
عجب قابلیت جالبی !! به این میگن تیوپل؟ کل قابلیت اش همینه؟ یعنی نوع دیگه ی تعریف و فراخونی نداره؟ الان دقیقا نوع ای که نوشتم ، از نوع کلاس ثابتی نیست؟
---------------------
بعد لینک دانلود ویژال استودیو با دات نت 4.7 رو دارین؟ یا اگه بشه جداگانه فایلی رو دانلود کرد که به ویژال استودیوی 2017 دات نت 4.7 رو اضافه کرد که عالی میشه
---------------------
بعد اینکه چرا در تابع Main در کلاس Program ، اتریباتس [STAThread] رو اضافه کردن؟ این چه اتریباتس ای هست؟ مگه تک نخی نیست؟ یعنی به تابع مین مون قابلیت تک نخی اجرا شدن رو میده؟ چرا multi thread apartment رو ندادن؟!
 
آخرین ویرایش:

the_king

مدیرکل انجمن
سلام استاد علی
آقا ، در لینک زیر ، گفت توی C# 7 که توی ویژال استودیو 2017 هست ، این قابلیت اضافه شد که بدون استفاده از کلمه کلیدی out ، چندین مقدار رو برگردوند :
K. G. Sreeju - C# 7 - Return multiple values from methods

ولی من مثل اون ، تابع مو تعریف میکنم ، ارور میده . تابع رو این جوری تعریف میکنم :


کد:
public (int, int) MyMethod11()
        {
            return (10, 20);
        }

متن ارور اینه :
Error CS8179 Predefined type 'System.ValueTuple`2' is not defined or imported
نسخه ی دات نت ام ، 4.6.2 هست .
دلیل اش چیه؟ بخاطر نسخه ی دات نت ام هست؟

ویرایش : ممنون . جوابشو پیدا کردم . طبق راهنمای این لینک :
Predefined type 'System.ValueTuple´2´ is not defined or imported
بخاطر نسخه ی 4.6.2 هست .که دستور زیر رو در NuGet زدم ، درست شد :
Install-Package "System.ValueTuple"
یا باید دات نت 4.7 باشه

---------------------
بعد اینکه ، تیوپل چیه؟
طبق مقاله ی زیر :
آشنایی با قابلیت های جدید سی شارپ 7.0
این کد رو تعریف کردم :

کد:
(int, string) a = (5, "salam");
            MessageBox.Show(a.Item2.ToString());
عجب قابلیت جالبی !! به این میگن تیوپل؟ کل قابلیت اش همینه؟ یعنی نوع دیگه ی تعریف و فراخونی نداره؟ الان دقیقا نوع ای که نوشتم ، از نوع کلاس ثابتی نیست؟
در NET 4.0 به بعد یه Tuple وجود داشت که اصل کارش همین بود که چند مقدار رو داخلش جای بده. یعنی System.Tuple
کد:
            var t = Tuple.Create<int, int, int>(12, 45, 99);
            MessageBox.Show(t.ToString());
و چون ماهیتش یک کلاس بود و value-type نبود یکسری مزایا داشت و یکسری معایب. و ارتباط خاصی هم با خود زبان نداشت، یک کلاس عادی بود.
بعد که ازش استقبال شد اومدن در نسخه جدید یه نمونه struct اش به اسم System.ValueTuple ساختند که هم value-type باشه و مثل آرایه ها در زبان ازش پشتیبانی ویژه بشه، طوری که مجبور نباشید صریحا از new ValueTuple و ValueTuple اسم ببرید. میتوانید با Object Browser ویژوال استدیو بررسی اش کنید.
بعد لینک دانلود ویژال استودیو با دات نت 4.7 رو دارین؟ یا اگه بشه جداگانه فایلی رو دانلود کرد که به ویژال استودیوی 2017 دات نت 4.7 رو اضافه کرد که عالی میشه
خیر ندارم.
بعد اینکه چرا در تابع Main در کلاس Program ، اتریباتس [STAThread] رو اضافه کردن؟ این چه اتریباتس ای هست؟ مگه تک نخی نیست؟ یعنی به تابع مین مون قابلیت تک نخی اجرا شدن رو میده؟ چرا multi thread apartment رو ندادن؟!
این مربوط به تک نخی یا نبودن خود نخ برنامه نیست، مربوط به تک نخی بودن یا نبودن ارتباطی ئه که با COM برقرار می کنه. از اونجایی که فرم ها با یکسری از منابع سیستم ارتباط COM دارند و طبق محدودیت های سیستم عامل الزاما باید ارتباط شون تک نخی باشه، این صفت رو اضافه می کنند. محدودیت مربوط به سیستم عامل ئه، مثل همون دسترسی به کنترل های فرم از یک نخ مجزا است.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
کلاس فرقی نداره اما برای دسترسی protected بین ایندو فرق وجود داره، protected به شما مجوز دسترسی به اون base رو میده نه همه Form1 ها. protected کاری به این نداره که فلان شیء از چه نوع کلاسی ئه، دسترسی هر instance اش صرفا برای اشیاء وارث همون instance محدود شده، شما از یک instance وارث دیگه نمی توانید به متغیری دسترسی داشته باشید که از یک instance دیگه است، حتی اگه از همون نوع کلاس باشه.
این تعریف دسترسی protected ئه، وگرنه مساله تفاوت کلاس base با هر Test1 ای نیست. شما با base و بدون base صرفا به myDinamicVar4 ای دسترسی دارید که برای همون شیء Test1 وجود داره و کد داخلش اجرا میشه. اون شیء که شما از کلاس form1Obj ساخته اید، از جنس کلاس والد Test1 ئه ولی این شیء هیچ ارتباطی با دسترسی protected برای شیء ای که شما اون کد رو داخل اجرا می کنید نداره، برای همین protected برای دسترسی اون کد به اون form1Obj.myDinamicVar4 کافی نیست. این محدودیت protected ئه.

ممنون استاد علی
ولی من دقیق متوجه منظورتون نشدم . باز هم به هر حال هر چی فکر میکنم ، شی ای که به پدر شی جاری اشاره میکنه یعنی کلمه ی کلیدی base و شی ای که از کلاس پدر خودمون جدید بسازیم ، نباید فرق خاصی کنه
به اضافه ی اینکه در کد که بهتون دادم یعنی :


کد:
namespace Practice_1
{
    public partial class Form1 : Form
    {
    protected static string myStaticVar3 = "internet download manager";
        protected string myDinamicVar4 = "Orbit Downloader";
        public string myDinamicVar5 = "padvish";
    }


    class Test1 : Form1
    {
    
        public void Method1()
        {
            Form1.myStaticVar3 = "";
            Form1 form1Obj = new Form1();
            form1Obj.myDinamicVar4

            Form1 a = base;
            Test1 b = this;
    }
    }
}

کد Form1 a = base; چرا اشتباه هست؟ یعنی چرا اشاره گر شی this رو میشه توی متغییر ریخت ولی base که به شی پدر اشاره میکنه رو چرا نمیشه ریخت؟


در NET 4.0 به بعد یه Tuple وجود داشت که اصل کارش همین بود که چند مقدار رو داخلش جای بده. یعنی System.Tuple
کد:
            var t = Tuple.Create<int, int, int>(12, 45, 99);
            MessageBox.Show(t.ToString());
و چون ماهیتش یک کلاس بود و value-type نبود یکسری مزایا داشت و یکسری معایب. و ارتباط خاصی هم با خود زبان نداشت، یک کلاس عادی بود.
بعد که ازش استقبال شد اومدن در نسخه جدید یه نمونه struct اش به اسم System.ValueTuple ساختند که هم value-type باشه و مثل آرایه ها در زبان ازش پشتیبانی ویژه بشه، طوری که مجبور نباشید صریحا از new ValueTuple و ValueTuple اسم ببرید. میتوانید با Object Browser ویژوال استدیو بررسی اش کنید.

خیر ندارم.

آها ممنون


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

SajjadKhati

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

کد:
Test1 test1Obj = new Test1();
            test1Obj.Method1();

در متد Method1() که در کلاس Test1 کلمه ی کلیدی this رو توی متغییر a ریختیم ، این کلمه ی کلیدی this در اینجا ، به شی test1Obj اشاره میکنه و اشاره گرشو توی متغییر a میریزه. یعنی کلمه ی کلیدی this ، از خودش چیزی نداره تا زمانی که از بیرون ، اون عضو از کلاس فراخونی نشه . خوب؟ حالا در اینجا ، کلمه ی کلیدی base رو که گفتیم ، خوب هر چند به شی پدر شی جاری که باعث فراخونی اون عضو از کلاس شد ، اشاره میکنه ولی در واقع همچین شی ای در بیرون اصلا ساخته نشده (هر چند شی فرزندش ساخته شده ولی اون شی فرزند هه) که با اون شی ، عضو مورد نظر از اون کلاس فراخونی شه . پس شی base به چی اشاره میکنه؟ متوجه ی منظورم میشین؟ یعنی ما وقتی کلمه ی کلیدی base رو بکار میبریم ، برخلاف کلمه ی کلیدی this ، خودش جداگانه شی ای (حالا شی جدید و ...) از کلاس پدر شی جاری میسازه و بعد میتونیم فراخونی کنیم اعضاشو؟ واسه همینه که کلمه ی کلیدی base (اشاره گر) رو نمیشه توی متغییری ریخت ؟
 

SajjadKhati

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

the_king

مدیرکل انجمن
ممنون استاد علی
ولی من دقیق متوجه منظورتون نشدم . باز هم به هر حال هر چی فکر میکنم ، شی ای که به پدر شی جاری اشاره میکنه یعنی کلمه ی کلیدی base و شی ای که از کلاس پدر خودمون جدید بسازیم ، نباید فرق خاصی کنه

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


به اضافه ی اینکه در کد که بهتون دادم یعنی :


کد:
namespace Practice_1
{
    public partial class Form1 : Form
    {
    protected static string myStaticVar3 = "internet download manager";
        protected string myDinamicVar4 = "Orbit Downloader";
        public string myDinamicVar5 = "padvish";
    }


    class Test1 : Form1
    {
   
        public void Method1()
        {
            Form1.myStaticVar3 = "";
            Form1 form1Obj = new Form1();
            form1Obj.myDinamicVar4

            Form1 a = base;
            Test1 b = this;
    }
    }
}

کد Form1 a = base; چرا اشتباه هست؟ یعنی چرا اشاره گر شی this رو میشه توی متغییر ریخت ولی base که به شی پدر اشاره میکنه رو چرا نمیشه ریخت؟

چون base جاش اونجا نیست، کدوم base؟ یک کلاس ممکنه ده تا base داشته باشه. base رو در متد override شده می نویسند که بشه به base اون دسترسی پیدا کرد. همونطور که this در داخل یک متد static معنی نداره اون base هم در متد override نشده معنی نداره. شما در Method1 که یک متد عادی ئه که base ای ندارید.

هر چند من دقیق متوجه منظورتون از کلمه ی "ارتباط COM دارند" نشدم
COM یک تکنولوژی ارتباطی قدیمی و مهم ئه که همچنان بخش های اساسی ای از سیستم عامل ازش استفاده می کنند و منسوخ نشده. ActiveX ها هم سیستم ارتباطی شون بر اساس همون COM ئه.
 

the_king

مدیرکل انجمن
یک سئوال دیگه اینکه در کد پست بالا ، وقتی کلمه ی کلیدی this را بکار میبریم ، به اون شی ای که باعث اجرای اون عضو از کلاس شد ، اشاره میکنه . یعنی مثلا اگه در کلاس Form1 ، یک دکمه بسازیم و توی رویداد کلیک اش این خط رو بنویسیم :

کد:
Test1 test1Obj = new Test1();
            test1Obj.Method1();

در متد Method1() که در کلاس Test1 کلمه ی کلیدی this رو توی متغییر a ریختیم ، این کلمه ی کلیدی this در اینجا ، به شی test1Obj اشاره میکنه و اشاره گرشو توی متغییر a میریزه. یعنی کلمه ی کلیدی this ، از خودش چیزی نداره تا زمانی که از بیرون ، اون عضو از کلاس فراخونی نشه . خوب؟ حالا در اینجا ، کلمه ی کلیدی base رو که گفتیم ، خوب هر چند به شی پدر شی جاری که باعث فراخونی اون عضو از کلاس شد ، اشاره میکنه ولی در واقع همچین شی ای در بیرون اصلا ساخته نشده (هر چند شی فرزندش ساخته شده ولی اون شی فرزند هه) که با اون شی ، عضو مورد نظر از اون کلاس فراخونی شه . پس شی base به چی اشاره میکنه؟ متوجه ی منظورم میشین؟ یعنی ما وقتی کلمه ی کلیدی base رو بکار میبریم ، برخلاف کلمه ی کلیدی this ، خودش جداگانه شی ای (حالا شی جدید و ...) از کلاس پدر شی جاری میسازه و بعد میتونیم فراخونی کنیم اعضاشو؟ واسه همینه که کلمه ی کلیدی base (اشاره گر) رو نمیشه توی متغییری ریخت ؟
بله، عبارات کلیدی this و base هیچکدوم باعث ساختن شدن شیء نمیشن. زمانی که شما شیء ای از کلاسی میسازید در پشت پرده شیء ای از کلاس والد اش هم ساخته اید، غیر از این نمیتونه باشه. شما نمیتوانید شیء از کلاس Form1 بسازید بدون اینکه از کلاس Form و ContainerControl و ScrollableControl و Control و ... شیء ساخته نشه. اینها ساخته می شوند چون والد اون کلاس اند. این base اشاره به همون یک شیء خاص از بین کلاس های والد ئه. تازه زمانی که شما می خواهید از base استفاده کنید ایجاد نشده، قبلا موقع ساختن شیء از کلاستون ساخته شده بود. چه ازش استفاده بکنید و چه نکنید وجود داشته.
 

the_king

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

SU-57

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

1- در solution explorer و در قسمت reference یک سری فابل قرار داره با پسوند dll که در قسمت path مسیر اون ها مشخص شده و حاوی توابعی هستند مثل system
الف) از کجا بفهمیم که توی هر کدوم از این فایل های dll چه توابعی وجود دارند
ب) در مسیر مشخص شده در کنار هر فایل dll یک فایل با نام مشابه با پسوند xml وجود داره این فایل های xml کاربردشون چیه

2- این جملات درسته:
الف )در c# می تونیم dll های managed شده رو به unmanaged تبدیل کنیم
ب) می تونیم dll های unmanaged رو وارد c# کنیم

3- در properties هر پروژه و در platform target گزینه Any cpu وجود داره
الف) اگه any cpu رو انتخاب کنیم دقیقا چه اتفاقی می افته یعنی اگه ویندوز ما 32 بیت باشه نرم افزار توی پوشه programfile نصب می شه که در اصل پوشه x86 است و اگه 64 بیت باشه باز هم تو پوشه programfile نصب می شه که در اصل پوشه 64 بیت است
ب) اگه x86 رو انتخاب کنیم فقط در ویندوز های 32 بیت نصب می شه؟
ج) اگه x64 بیت رو انتخاب کنیم فقط در ویندوز های 64 بیت نصب می شه؟ و روی ویندوز 32 بیت نمی تونه نصب بشه؟
اگه فقط توی ویندوزهای 64 بیت نصب می شه توی پوشه programfile(x86) نصب می شه یا تو پوشه programfile
 

SajjadKhati

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

1- در solution explorer و در قسمت reference یک سری فابل قرار داره با پسوند dll که در قسمت path مسیر اون ها مشخص شده و حاوی توابعی هستند مثل system
الف) از کجا بفهمیم که توی هر کدوم از این فایل های dll چه توابعی وجود دارند
ب) در مسیر مشخص شده در کنار هر فایل dll یک فایل با نام مشابه با پسوند xml وجود داره این فایل های xml کاربردشون چیه

2- این جملات درسته:
الف )در c# می تونیم dll های managed شده رو به unmanaged تبدیل کنیم
ب) می تونیم dll های unmanaged رو وارد c# کنیم

3- در properties هر پروژه و در platform target گزینه Any cpu وجود داره
الف) اگه any cpu رو انتخاب کنیم دقیقا چه اتفاقی می افته یعنی اگه ویندوز ما 32 بیت باشه نرم افزار توی پوشه programfile نصب می شه که در اصل پوشه x86 است و اگه 64 بیت باشه باز هم تو پوشه programfile نصب می شه که در اصل پوشه 64 بیت است
ب) اگه x86 رو انتخاب کنیم فقط در ویندوز های 32 بیت نصب می شه؟
ج) اگه x64 بیت رو انتخاب کنیم فقط در ویندوز های 64 بیت نصب می شه؟ و روی ویندوز 32 بیت نمی تونه نصب بشه؟
اگه فقط توی ویندوزهای 64 بیت نصب می شه توی پوشه programfile(x86) نصب می شه یا تو پوشه programfile

سلام آقا رامین
1) اون system ، تابع نیست . فضای نام هست که داخلش کلاس و داخل کلاس هم اعضای کلاس مثل تابع و ... هست (مبحث کلاس و فضای نام ، به مبحث شی گرایی برمیگرده)
الف) روی همون فایل در solution explorer کلیک راست و view in object browser رو بزن . بعد با انتخاب علامت فلش کنار نوشته ، به اعضای (کلاس و اعضای کلاس) اون فضای نام میان البته اگه برنامه نوشته شده تحت دات نت باشه
ب) نمیدونم

2)
الف) اگه منظورت ، نوشتن هست بله ، در سی شارپ میشه کدهای unmanaged هم نوشت
ب) بله

3)
الف) احتمالا پروژه ، بسته به نوع سیستم عامل طرف ، متغییر میشه
ب و ج) نه . احتمالا نوع پروژه رو فقط تغییر میده (مثل نرم افزارهای 32 بیت که توی 64 بیت هم نصب میشن) ولی این گزینه ها بیشتر زمان نوشتن برنامه های unmanaged کاربرد داره که باید طبق نوع برنامه ی هدف ، نوع 32 یا 64 بیت بودنش مشخص شه
 

SU-57

Active Member
سلام آقا رامین
1) اون system ، تابع نیست . فضای نام هست که داخلش کلاس و داخل کلاس هم اعضای کلاس مثل تابع و ... هست (مبحث کلاس و فضای نام ، به مبحث شی گرایی برمیگرده)
الف) روی همون فایل در solution explorer کلیک راست و view in object browser رو بزن . بعد با انتخاب علامت فلش کنار نوشته ، به اعضای (کلاس و اعضای کلاس) اون فضای نام میان البته اگه برنامه نوشته شده تحت دات نت باشه
ب) نمیدونم

2)
الف) اگه منظورت ، نوشتن هست بله ، در سی شارپ میشه کدهای unmanaged هم نوشت
ب) بله

3)
الف) احتمالا پروژه ، بسته به نوع سیستم عامل طرف ، متغییر میشه
ب و ج) نه . احتمالا نوع پروژه رو فقط تغییر میده (مثل نرم افزارهای 32 بیت که توی 64 بیت هم نصب میشن) ولی این گزینه ها بیشتر زمان نوشتن برنامه های unmanaged کاربرد داره که باید طبق نوع برنامه ی هدف ، نوع 32 یا 64 بیت بودنش مشخص شه

ممنونم از لطف شما


1- آیا اگه بخوام برنامه من فقط روی سیستم عامل های 32 بیت نصب بشه باید روی x86 بذارم؟
اینجا یک مشکلی وجود داره چون برنامه های 32 بیت هم می تونن روی 64 بیت نصب بشن پس باید چیکار کنیم که فقط روی 32 بیت نصب بشن
من برنامه های زیادی هم دیدم که 32 بیت هستن و فقط روی 32 بیت نصب می شن و روی 64 نصب نمی شن و قاعدتا باید نصب بشن!

2- آیا اگه بخوام برنامه من فقط روی سیستم های 64 بیت نصب بشه باید بذارم روی x64 ؟ (این فکر می کنم درست باشه)

3- اگه بخوام برنامه من هم در سیستم های 32 بیت و هم 64 بیت نصب بشن به این صورت که تو سیستم های 32 بیت برن تو پوشه programfile و تو نسخه های 64 بیت برن تو پوشه programfile که 64 بیت است باید روی Any cpu بذارم؟

4- بعضی برنامه ها هستن که دو نسخه دارن هم 32 بیت و هم 64 بیت. یعنی اینا اومدن یکبار روی x86 گذاشتن و کامپایل کردن و یکبار x64 گذاشتن و کامپایل کردن. ایا در اینجا کدها یکسانه فقط در دو حالت کامپایل می کنن؟
اینجا یک تناقضی وجود داره چون برنامه ای مثل diskeeper نسخه 32 بیتش روی 64 نصب نمی شه در حالی که طبق تئوری وقتی x86 میذاریم باید روی 64 بیت هم نصب بشه
 

the_king

مدیرکل انجمن
ب) در مسیر مشخص شده در کنار هر فایل dll یک فایل با نام مشابه با پسوند xml وجود داره این فایل های xml کاربردشون چیه
کاربرد های خیلی متنوعی داره، چون فرمت XML اجازه ذخیره سازی انواع اطلاعات رو میده، اما معمولا فایل XML کنار یک فایل dll مستندات و راهنمای استفاده شه، داخل همون ویژوال استدیو هم لابلای سطر های کد تایپ می شه و بعد بصورت خودکار همراه dll ئه ایجاد میشه، مثلا میگه این متد (تابع) که کدش رو می نویسید کارش اینه (یکسری توضیحات متنی معمولا انگلیسی) و توضیحات پارامتر های اون تابع و اینکه اگه خطایی رخ بده چطور خطاهایی رو ایجاد می کنه. اینها یکسری سطر های متن انگلیسی اند با یک فرمت کلی XML، شبیه محتویات فایل های HTML
اصولا dll ای که برای استقاده توسط اشخاص دیگه طراحی میشه این توضیحات رو لازم داره. این XML اگه کنارش نباشه از توضیحات خبری نیست. فایل مجزا بودنش این مزیت رو داره که هم راحت ویرایش بشه و بشه به زبان های مختلف ایجادش کرد، فرضا راهنمای فارسی و راهنمای انگلیسی در دو فایل مجزا که هر کدوم کنار اون فایل dll باشه توضیحات به همون زبان باشه.

2- این جملات درسته:
الف )در c# می تونیم dll های managed شده رو به unmanaged تبدیل کنیم
نه، میتوانید بین محیط Managed و Unmanaged ارتباط برقرار کنید ولی اینکه بینشون ارتباط برقرار میشه به این معنی نیست که خود محیط Managed ئه #C تبدیل به Unmanaged بشه، همچنان Managed باقی میمونه ولی با محیط Unmanaged ارتباط برقرار می کنه.

ب) می تونیم dll های unmanaged رو وارد c# کنیم
تقریبا، معمولا می توانیم از dll های Unmanaged در #C استفاده کنیم.

3- در properties هر پروژه و در platform target گزینه Any cpu وجود داره
الف) اگه any cpu رو انتخاب کنیم دقیقا چه اتفاقی می افته یعنی اگه ویندوز ما 32 بیت باشه نرم افزار توی پوشه programfile نصب می شه که در اصل پوشه x86 است و اگه 64 بیت باشه باز هم تو پوشه programfile نصب می شه که در اصل پوشه 64 بیت است
وقتی یک پروژه NET. رو به فایل اجرایی exe و dll تبدیل می کنید، فایل اجرایی ساخته شده کامپایل شده، ولی به زبان ماشین واقعی نیست. یعنی مثل فایل اجرایی دیگه نیست که کامپیوتر مستقیما زبونش رو بفهمه و مستقیما هم اجرا کنه. یک زبان مخصوص داره که برای ماشین مجازی مخصوص به خود NET. ئه. این ماشین مجازی میتونه همون لحظه که داره فایل اجرایی رو اجرا می کنه تصمیم بگیره که 32 بیتی باشه یا 64 بیتی باشه. اگه اون تنظیم رو Any CPU قرارش بدید نوعی رو انتخاب می کنه که با سیستم سازگاره. یعنی یک فایل exe یا dll ای می سازه که هر جا کپی اش کنید و اجرا کنید 32 بیتی و 64 بیتی بودنش درست تو لحظه شروع اجرا تعیین میشه و بدون مشکل تغییر می کنه.
Any CPU گزینه خیلی خوبی هم هست، چون اگه ویندوز 64 بیتی باشه برنامه 64 بیتی هم سریعتر اجرا میشه و هم محدودیت هاش کمتر ئه. ولی گاهی تو کدتون موردی دارید که مجبور هستید 32 بیتی اجراش کنید، فرضا از یک DLL ئه Unmanaged استفاده کرده اید که اصلا نسخه 64 بیتی نداشته. اگه برنامه شما بخواد 64 ببتی اجرا بشه دیگه نمیتونه از DLL ئه 32 بیتی استفاده کنه، اگه همچین کاری بکنه برنامه Crash می کنه و از کار می افته.
اینجور مواقع هست که مجبورید از حالت Any CPU درش بیارید.

ب) اگه x86 رو انتخاب کنیم فقط در ویندوز های 32 بیت نصب می شه؟
نه، همچین محدودیتی ایجاد نمیشه. ویندوز های 64 بیتی به ندرت مشکلی برای اجرا کردن برنامه های 32 بیتی دارند. خیلی از برنامه هایی که روی ویندوز 64 بیتی اجرا می کنید فقط یک نسخه دارند که اونم 32 بیتی ئه و هم روی ویندوز 32 بیتی و هم روی ویندوز 64 بیتی قابل اجرا هستند. اینطوری نیست که چون 32 بیتی شده دیگه ویندوز 64 بیتی نتونه اجراش کنه. اگه x86 رو انتخاب کنید برنامه بصورت 32 بیتی اجرا میشه، هم روی ویندوز 32 بیتی اجرا میشه و هم روی ویندوز 64 بیتی. فقط فرقش اینه که روی ویندوز 64 بیتی هم بصورت 32 بیتی اجرا میشه.

ج) اگه x64 بیت رو انتخاب کنیم فقط در ویندوز های 64 بیت نصب می شه؟ و روی ویندوز 32 بیت نمی تونه نصب بشه؟
بله، فقط در نظر بگیرید که معمولا برنامه های NET. ای به نصب شدن احتیاجی ندارند، فقط فایلشون کپی بشه برای اجرا شدن کافیه. البته به تنظیمات و مشخصات برنامه هم بستگی داره ولی عموما برنامه های NET. ای ماهیتشون واقعا به نصب شدن احتیاج نداره. در هر صورت برنامه های 64 بیتی روی ویندوز 32 بیتی قابل اجرا نیستند.

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

the_king

مدیرکل انجمن
ممنونم از لطف شما
1- آیا اگه بخوام برنامه من فقط روی سیستم عامل های 32 بیت نصب بشه باید روی x86 بذارم؟
نه، کافی نیست، اگه بهمین اکتفا کنید برنامه تون بدون مشکل روی ویندوز 64 بیتی اجرا میشه.
باید در کد برنامه تون یا در Setup ساز برنامه تون بررسی بشه که سیستم عامل 64 بیتی هست یا خیر که اگه 64 بیتی بود با یک پیغام مناسب اجرا متوقف بشه. این یک محدودیت فنی نیست، چیزی است که خودتون میخواهید بصورت محدودیت به کاربر اعلام کنید. وگرنه اگر بخواهید ویندوز 64 بیتی برای اجرا کردنش مشکلی نداره.

اینجا یک مشکلی وجود داره چون برنامه های 32 بیت هم می تونن روی 64 بیت نصب بشن پس باید چیکار کنیم که فقط روی 32 بیت نصب بشن
من برنامه های زیادی هم دیدم که 32 بیت هستن و فقط روی 32 بیت نصب می شن و روی 64 نصب نمی شن و قاعدتا باید نصب بشن!
اغلب Setup ساز ها تنظیماتی دارند که مشخص بشه روی چه نسخه های ویندوزی و از چه نوعی قابل نصب باشند. این محدودیت رو به خود برنامه اجرایی ربط ندید، تنظیمی ئه که در برنامه Setup ساز ایجاد می کنید.

2- آیا اگه بخوام برنامه من فقط روی سیستم های 64 بیت نصب بشه باید بذارم روی x64 ؟ (این فکر می کنم درست باشه)
بله.

3- اگه بخوام برنامه من هم در سیستم های 32 بیت و هم 64 بیت نصب بشن به این صورت که تو سیستم های 32 بیت برن تو پوشه programfile و تو نسخه های 64 بیت برن تو پوشه programfile که 64 بیت است باید روی Any cpu بذارم؟
بله، اما باید کد برنامه تون هم طوری نوشته بشه که در هر دو حالت درست اجرا بشه. فرضا اگه بخواهید در برنامه تون از یک کمپوننت ActiveX یا یک DLL ئه Unmanaged استفاده کنید معمولا برنامه تون نمیتونه 64 بیتی اجرا بشه چون اکثر ActiveX و DLL های Unmanaged فقط نسخه 32 بیتی دارند و برنامه تون نمیتونه 64 بیتی باهاشون کار کنه.

4- بعضی برنامه ها هستن که دو نسخه دارن هم 32 بیت و هم 64 بیت. یعنی اینا اومدن یکبار روی x86 گذاشتن و کامپایل کردن و یکبار x64 گذاشتن و کامپایل کردن. ایا در اینجا کدها یکسانه فقط در دو حالت کامپایل می کنن؟
اینجا یک تناقضی وجود داره چون برنامه ای مثل diskeeper نسخه 32 بیتش روی 64 نصب نمی شه در حالی که طبق تئوری وقتی x86 میذاریم باید روی 64 بیت هم نصب بشه
بله، ولی معمولا چیزی بیشتر از یک تغییر یک تنظیم ئه. خیلی بعیده که کد ها عینا یکسان باشند. توی کد یکسری تفاوت های کوچک اما مهم هست که اگه نبود برنامه موقع اجرا از کار می افتاد
مثلا در کد 32 بینی طول حافظه رو با فرمول n * 4 حساب کرده، چون هر 32 بیت چهار بایته و در نسخه 64 بیتی با فرمول n * 8 . طبیعتا این تفاوت خیلی آنچنانی نیست، ولی مهمه.
نصب شدن با اجرا شدن خیلی فرق داره، مخصوصا برای برنامه ای که قراره با هسته سیستم عامل یا یکسری dll ها کار کنه که نسخه 32 بیتی و 64 بیتی شون جدا است. اگه جابجا dll ها فراخوانی بشه از کار می افتند.
مثلا توی نسخه 32 بیتی با کتابخانه test.dll کار می کنه و در نسخه 64 بیتی با کتابخانه test64.dll. این رو توی کد برنامه نوشته اند. ظاهر کد شبیه همه اما جای test.dll با test64.dll عوض شده.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
بعد لینک دانلود ویژال استودیو با دات نت 4.7 رو دارین؟ یا اگه بشه جداگانه فایلی رو دانلود کرد که به ویژال استودیوی 2017 دات نت 4.7 رو اضافه کرد که عالی میشه

سلام
ممنون استاد علی
الان متوجه شدم وقتی در ویژال استودیو ، در لیست کشویی ایس که نسخه ی دات نت فریم وورک رو برای پروژه انتخاب میکنیم ، یه گزینه ای بنام More Framework داره که اگه بزنیم ، به لینک زیر هدایت میشم برای دانلود جدید ترین دات نت فریم وورک ها :

Targeting .NET Platforms

هر کدوم از دات نت فریم وورک ها 2 قسمت دارن . یکی بنام .NET Framework 4.7 Runtime که لینک برای اجرای برنامه های نوشته شده در دات نت فریم وورک هست .
یه لینک دیگه ، لینک .NET Framework 4.7 Developer Pack هست که اگه دانلود و نصب کنیم ، همون نسخه ی دات نت فریم وورک رو به ویژال استودیو اضافه میکنه
ممنون

---------------------------------------------------------------------------

استاد علی ، میگم من ویژال استودیو 2017 ام رو آپدیت کردم . چون آپدیت سنگینی بود و حدودا 1 گیگ بود ، شما نمیدونین فایل آپدیت اش کجا دقیقا ذخیره شد که وقتی بعدا دوباره ویژال استودیو ام رو در سیستم عامل دیگه نصب کردم ، این آپدیت رو هم همراش نصب کنم؟
ممنون
 
آخرین ویرایش:

the_king

مدیرکل انجمن
استاد علی ، میگم من ویژال استودیو 2017 ام رو آپدیت کردم . چون آپدیت سنگینی بود و حدودا 1 گیگ بود ، شما نمیدونین فایل آپدیت اش کجا دقیقا ذخیره شد که وقتی بعدا دوباره ویژال استودیو ام رو در سیستم عامل دیگه نصب کردم ، این آپدیت رو هم همراش نصب کنم؟
ممنون
نه، کلا دانلود نکردم و ندارمش. باید پاسخ رو تو سایت مایکروسافت و فروم هاش جستجو کنید.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
سلام
استاد علی ، درباره ی کلمه کلیدی this ، سئوالاتی اضافی تر دارم . الان کلمه ی کلیدی this ، فقط به شی ای از همون کلاس اشاره داره دیگه؟ درسته؟ :
در کد زیر :

کد:
    namespace NameSpaceTest1
    {
        public class Father
        {
            public string fatherMember;
            public Father()
            {
                this.fatherMember = "Father";

            }
        }

        public class Child : Father
        {
            public Child()
            {
                this.fatherMember = "Child";
            }
        }
    }

وقتی در جایی (مثلا در یه کلاس دیگه) ، شی ای از کلاس Child ساخته شه مثلا :
کد:
private void btnClass2_Click(object sender, EventArgs e)
        {
            NameSpaceTest1.Father a = new NameSpaceTest1.Child();
        }

وقتی کدی که در کلاس پدر هست اجرا میشه یعنی کد :
کد:
this.fatherMember = "Father";
در اینجا ، کلمه ی کلیدی this ، با اونکه موقع فراخونی شی ای از کلاس Child بود ، ولی بازم به کلاسی که توش هست یعنی کلاس Father اشاره میکنه دیگه؟ درسته؟

اینو گفتم تا قضیه ی زیر رو بگم :
من یه DefaultUserControl ساختم که از UserControl ها ارث میبره . بعد UserControl هایی بنام Page1 و Page2 ساختم که از DefaultUserControl به ارث میبره . داخل کلاس DefaultUserControl هم فقط دکمه هایی گذاشتم که شی ای از کلاس های Page1 و Page2 و ... بسازه زمانی که روی دکمه ی مورد نظر کلیک میشه
همون اول هم در متد سازنده ی فرم ام (بنام MainForm) ، یه شی ای از کلاس Page2 ساختم که مستقیما این شی ساخته شه .
حالا توی رویداد دکمه های Page1 و Page2 در کلاس DefaultUserControl هم علاوه بر کدهایی که مربوط به کارم هست ، کد زیر رو نوشتم :
کد:
this.Dispose();
سئوالم اینه که این this ، که در کلاس DefaultUserControl نوشتم ، اشاره گر به شی کلاس DefaultUserControl هست یا شی Page1 و ... ؟
یعنی الان شی کلاس پدر رو که DefaultUserControl هست ، نابود میکنه و یا اینکه شی کلاس فرزند که Page1 یا Page2 هست؟
طبق تعریف this ، باید شی کلاس خودش یعنی DefaultUserControl باشه دیگه؟
سئوال دوم اینکه ، وقتی شی جدید از کلاس Page1 یا Page2 میسازم ، و بعد به فرم اضافه میکنم ، روی شی قبلی ای که از Page1 یا Page2 ساخته بودم ، اضافه نمیشه؟ یعنی حتما باید شی قبلی رو Dispose کنم تا شی جدید نشون بده. چرا؟
سوم اینکه همه ی کلاس هایی که از کلاس component ارث بری میکنن ، مگه در پنل ToolBax بعد از اجرا کردن پروژه ، در اونجا اضافه نمیشن؟ پس چرا DefaultUserControl و Page1 اضافه شدن برام ولی Page2 اضافه نشد؟!


اگه کدها رو بخواین ، اینن :
MainForm :
کد:
namespace Practice_1
{
    public partial class MainForm : Form
    {
        private DefaultUserControl defaultUserControl1;

        public MainForm()
        {
            InitializeComponent();

            //defaultUserControl1 = new Page2 { mainForm = this, myPage_2 = "salam" };
            defaultUserControl1 = new Page2(this);
            this.Controls.Add(defaultUserControl1);
        }
    }
}

DefaultUserControl :
کد:
namespace Practice_1
{
    public partial class DefaultUserControl : UserControl
    {
        public Form mainForm;

        public DefaultUserControl()
        {
            InitializeComponent();
        }

        public DefaultUserControl(Form syncForm_UsrCtrl)
        {
            InitializeComponent();
            mainForm = syncForm_UsrCtrl;
            this.Size = mainForm.ClientSize;
            this.Tag = "DefaultUserControl";
        }

        private void btnPage1_Click(object sender, EventArgs e)
        {
            Page1 page1 = new Page1(mainForm);
            mainForm.Controls.Add(page1);
            this.Dispose();
            // ((Page2)this).myPage_2 = "jk";
        }

        private void btnPage2_Click(object sender, EventArgs e)
        {
            Page2 page1 = new Page2(mainForm);
            mainForm.Controls.Add(page1);
            this.Dispose();
        }
    }
}

Page2 :
کد:
namespace Practice_1
{
    public partial class Page2 : DefaultUserControl
    {
        public Page2()
        {
            InitializeComponent();
        }

        public Page2(Form mainForm) : base(mainForm)
        {
            InitializeComponent();
            this.Tag = "Page2";
        }

        public void btnClass1_Click(object sender, EventArgs e)
        {
            Page2 a = this;
        }

        private void btnClass2_Click(object sender, EventArgs e)
        {
            NameSpaceTest1.Father a = new NameSpaceTest1.Child();
        }
    }
}

Page1 هم مثل Page2 از DefaultUserControl به ارث میبره ولی رویدادهاش متفاوت ان و شی های دکمه هاش
اینم شی بصری از DefaultUserControl :
0.JPG

و Page2 :
1.JPG
 

the_king

مدیرکل انجمن
سلام
استاد علی ، درباره ی کلمه کلیدی this ، سئوالاتی اضافی تر دارم . الان کلمه ی کلیدی this ، فقط به شی ای از همون کلاس اشاره داره دیگه؟ درسته؟ :
در کد زیر :

کد:
    namespace NameSpaceTest1
    {
        public class Father
        {
            public string fatherMember;
            public Father()
            {
                this.fatherMember = "Father";

            }
        }

        public class Child : Father
        {
            public Child()
            {
                this.fatherMember = "Child";
            }
        }
    }

وقتی در جایی (مثلا در یه کلاس دیگه) ، شی ای از کلاس Child ساخته شه مثلا :
کد:
private void btnClass2_Click(object sender, EventArgs e)
        {
            NameSpaceTest1.Father a = new NameSpaceTest1.Child();
        }

وقتی کدی که در کلاس پدر هست اجرا میشه یعنی کد :
کد:
this.fatherMember = "Father";
در اینجا ، کلمه ی کلیدی this ، با اونکه موقع فراخونی شی ای از کلاس Child بود ، ولی بازم به کلاسی که توش هست یعنی کلاس Father اشاره میکنه دیگه؟ درسته؟

اینو گفتم تا قضیه ی زیر رو بگم :
من یه DefaultUserControl ساختم که از UserControl ها ارث میبره . بعد UserControl هایی بنام Page1 و Page2 ساختم که از DefaultUserControl به ارث میبره . داخل کلاس DefaultUserControl هم فقط دکمه هایی گذاشتم که شی ای از کلاس های Page1 و Page2 و ... بسازه زمانی که روی دکمه ی مورد نظر کلیک میشه
همون اول هم در متد سازنده ی فرم ام (بنام MainForm) ، یه شی ای از کلاس Page2 ساختم که مستقیما این شی ساخته شه .
حالا توی رویداد دکمه های Page1 و Page2 در کلاس DefaultUserControl هم علاوه بر کدهایی که مربوط به کارم هست ، کد زیر رو نوشتم :
کد:
this.Dispose();
سئوالم اینه که این this ، که در کلاس DefaultUserControl نوشتم ، اشاره گر به شی کلاس DefaultUserControl هست یا شی Page1 و ... ؟
this به هیچ کلاسی اشاره نمی کنه، به Instance اشاره می کنه، به شیء ای که ساخته شده. این شیء ممکنه از ترکیب چندین کلاس و اینترفیس ساخته شده باشه ولی به هر حال یک شیء ئه.
اینکه این شیء از چه نوعی باشه به خود this ربطی نداره، Instance همیشه یکی ئه، چند تا نیست که بگیم this داخلی ئه یا خارجی. این نوع به اون new ای ربط داره که توسطش کلاس ساخته میشه. شما میتوانید در کلاس DefaultUserControl تون یک متد داشته باشید که this اش رو برگردونه ولی اگه از کلاس Page1 شیء با متغیر x ساخته باشید و از اون متد استفاده کنید شیء برگردونده شده رفتارش مطابق کلاس Page1 ئه، نه DefaultUserControl. شما با this گرفتن در کلاس های داخلی تر نمی توانید ماهیت اش رو تغییر بدید.
کد:
    class C : B
    {
    }

    class B : A
    {
        public B GetThis()
        {
            return this;
        }
    }

    class A
    {
    }

کد:
            C c = new C();
            B b = c.GetThis();
            MessageBox.Show(b.GetType().ToString());

اگه ارث بری رو یک توپ چند لایه در نظر بگیرید که کلاس داخلی هسته و پدر سایر کلاس ها است، همیشه اون لایه خارجی ئه که در معرض تماس ئه.
اون this اشاره به خارجی ترین کلاس می کنه. میتوانید شی رو در یک متغیر از نوع UserControl قرار بدید ولی ماهیتش عوض نمیشه. متدی هم که Override شده دیگه با تغییر متغیر به حالت قبلی بر نمیگرده.
اگر در کلاس خارجی تر متدی تغییر رفتار داده دیگه در هر متغیری که قرارش بدید مطابق همون متد اجرا میشه که در آخرین لایه override شده بود.
یعنی الان شی کلاس پدر رو که DefaultUserControl هست ، نابود میکنه و یا اینکه شی کلاس فرزند که Page1 یا Page2 هست؟
البته هیچکدوم رو که نابود نمی کنه، متدی رو اجرا می کنه که منابع خارحی شون رو نابود می کنه، خودشون سرجاشون هستن. قبلا در این مورد که Dispose چیکار می کنه صحبت کردیم.
اما در این مورد که کدوم متد Dispose اجرا میشه به این بستگی داره که خارجی ترین کلاسی که Dispose رو override کرده یا new اش کرده (متد override شده رو کنار گذاشته و یه متد جدید با همون اسم بازنویسی کرده) کدومه.
همون خارجی ترین متد ئه که اجرا میشه، حالا ممکنه در کدش قبلی ها رو هم با base صدا بکنه یا نکنه. بستگی به کدش داره، الزامی نداره که قبلی ها رو هم اجرا کنه.

طبق تعریف this ، باید شی کلاس خودش یعنی DefaultUserControl باشه دیگه؟
نه، تعریف نمی گه که this باید کلاس فلان باشه، this شیء instance رو بر می گردونه، با نوع DefaultUserControl قطعا سازگار ئه و قطعا یک DefaultUserControl محسوب میشه، در این شکی نیست، ولی شیء this ممکنه از نوع وارثان DefaultUserControl باشه، نه خود DefaultUserControl .
سئوال دوم اینکه ، وقتی شی جدید از کلاس Page1 یا Page2 میسازم ، و بعد به فرم اضافه میکنم ، روی شی قبلی ای که از Page1 یا Page2 ساخته بودم ، اضافه نمیشه؟ یعنی حتما باید شی قبلی رو Dispose کنم تا شی جدید نشون بده. چرا؟
کنترل های جدید نشون داده بشن متوجه اضافه شدنشون میشین؟ نه کدی برای تعیین موقعیت و ابعاد دارید و نه جا باز کردن برای نمایش اش. قاعدتا روی قبلی هم بشینه کنترل زیرش مخفی میشه و به دلیل تشابه شون تغییر ظاهری هم نداره.
سوم اینکه همه ی کلاس هایی که از کلاس component ارث بری میکنن ، مگه در پنل ToolBax بعد از اجرا کردن پروژه ، در اونجا اضافه نمیشن؟ پس چرا DefaultUserControl و Page1 اضافه شدن برام ولی Page2 اضافه نشد؟!
اول امتحان کنید ببینید اصلا Page1 در Toolbox قابل استفاده است؟ اگه با خطا متوقف بشه از Toolbox حذف میشه. باید Build پروژه رو روی x86 قرار بدید و یا در سیستم 32 بیتی کار کنید.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
this به هیچ کلاسی اشاره نمی کنه، به Instance اشاره می کنه، به شیء ای که ساخته شده. این شیء ممکنه از ترکیب چندین کلاس و اینترفیس ساخته شده باشه ولی به هر حال یک شیء ئه.
اینکه این شیء از چه نوعی باشه به خود this ربطی نداره، Instance همیشه یکی ئه، چند تا نیست که بگیم this داخلی ئه یا خارجی. این نوع به اون new ای ربط داره که توسطش کلاس ساخته میشه. شما میتوانید در کلاس DefaultUserControl تون یک متد داشته باشید که this اش رو برگردونه ولی اگه از کلاس Page1 شیء با متغیر x ساخته باشید و از اون متد استفاده کنید شیء برگردونده شده رفتارش مطابق کلاس Page1 ئه، نه DefaultUserControl. شما با this گرفتن در کلاس های داخلی تر نمی توانید ماهیت اش رو تغییر بدید.
ممنون استاد علی
میدونم به شی اشاره میکنه (حالا گاها فراموش کردم ، شی رو بنویسم و اشتباها کلاس نوشتم)
هر چند با مثال زیر ، درکش برام بهتر شد ولی من قشنگ متوجه ی این جمله تون نشدم


کد:
    class C : B
    {
    }

    class B : A
    {
        public B GetThis()
        {
            return this;
        }
    }

    class A
    {
    }

کد:
            C c = new C();
            B b = c.GetThis();
            MessageBox.Show(b.GetType().ToString());

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

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


البته هیچکدوم رو که نابود نمی کنه، متدی رو اجرا می کنه که منابع خارحی شون رو نابود می کنه، خودشون سرجاشون هستن. قبلا در این مورد که Dispose چیکار می کنه صحبت کردیم.
اما در این مورد که کدوم متد Dispose اجرا میشه به این بستگی داره که خارجی ترین کلاسی که Dispose رو override کرده یا new اش کرده (متد override شده رو کنار گذاشته و یه متد جدید با همون اسم بازنویسی کرده) کدومه.
همون خارجی ترین متد ئه که اجرا میشه، حالا ممکنه در کدش قبلی ها رو هم با base صدا بکنه یا نکنه. بستگی به کدش داره، الزامی نداره که قبلی ها رو هم اجرا کنه.

نه . من متد Dispose رو override نکردم (نه در کلاس DefaultUserControl و نه در Page1 یا Page2)
حالا برای کدوم شی این Dispose رو اجرا میکنه؟ برای شی ای از کلاس DefaultUserControl یا Page2 ؟

اول امتحان کنید ببینید اصلا Page1 در Toolbox قابل استفاده است؟ اگه با خطا متوقف بشه از Toolbox حذف میشه. باید Build پروژه رو روی x86 قرار بدید و یا در سیستم 32 بیتی کار کنید.
بله قابل استفاده هست . با خطا هم متوقف نشد و درست کار میکنه
Build اش هم روی x86 هه
 

the_king

مدیرکل انجمن
من این قضیه رو تا حالا نمیدونستم . در خط دوم کد ، با اونکه نوعش B هست پس چطور C رو برمیگردونه؟!!

دلیلش این که چند تا شی instance مجزا که نیستن که هربار یکی شون رو برگردونه ، یه instance بیشتر نیست. Instance اش با B سازگاره و B محسوب میشه ولی نوعش B نیست.

خط اول و مثال توپ رو هم قشنگ متوجه نشدم
یه منبع فارسی و واضح دارین که درباره ی این قضایا صحبت کنه؟ من خیلی روی this (و اینکه آیا this میتونه غیر از شی کلاس خودش ، به شی ای از کلاس دیگه هم اشاره کنه یا نه فکر کردم ، مخصوصا در کدی که در پست بالا در قضیه ی Dispose بهتون دادم ، ولی به جواب درست نرسیدم) . نمیدونم درباره ی چی باید تحقیق کنم . صرف تحقیق روی ارث بری و یا کلمه ی کلیدی this هم جواب نمیده . یا همین کدی که نوشتین رو نمیدونم از لحاظ علمی با اونکه نوعش B هست ، چرا C رو برمیگردونه؟ یه منبعی که درباره ی این مسائل توضیح مو شکافانه بده ، ندارین؟
شما قبلا از متد Controls.Add استفاده کردین. پارامتر ورودی اش از چه نوعیه؟ Control ئه. نه Button و نه TextBox و نه هر نوع وراثت دیگه ای . پس چرا اونجا تعجب نمی کنین که پارامتر ورودی اش Control ئه اما روی فرم Button1 و TextBox1 و UserControl1 و ... به درستی قرار می گیره و تبدیل به Control خالی نمیشن؟ اگه شما این رو مبنا قرار می دیدن که چون this از نوع B ئه پس باید یک شیء با ماهیت B رو برگردونه و نباید از نوع C باشه پس باید براتون غیر قابل قبول باشه که Controls.Add یک Control رو دریافت کنه ولی روی فرم یک TextBox یا Button یا هر وارث دیگه ای از Control قرار بگیره.

اینم مثل همونه، مثل قضیه متغیر های object ئه. شما می توانید Button ها رو در object قرار بدید چون هر Button ای یک Object ئه، همانطور که هر Button ای یک Control ئه. ولی این به این معنی نیست که چون از object استفاده کردید دیگه رفتار اون شیء مثل دکمه ها نباشه و فرضا روی فرم نتونید قرارش بدید. همچنان یک Button ئه، چه در object قرارش بدید و چه در Control به هر حال یک دکمه است. this شبیه یک فیلد ئه که نوعش B باشه، حالا اگه داخلش یک شی از نوع C باشه همون شیء C رو بر می گردونه، وراثتش رو که حذف نمی کنه که بگیم باید تبدیل میشد به نوع B.
قواعد وراثت در #C به این شکل ئه، اگر غیر از این بود که شما نمی توانستید از Control.Add استفاده کنید.

نه . من متد Dispose رو override نکردم (نه در کلاس DefaultUserControl و نه در Page1 یا Page2)
حالا برای کدوم شی این Dispose رو اجرا میکنه؟ برای شی ای از کلاس DefaultUserControl یا Page2 ؟
عملا همه شون، ولی هر کدوم این اختیار رو داره که به داخلی تر ها اجازه اجرا بده یا نده. سلسله مراتبی میره عقب و اجرا میشن تا به متد Dispose ای برسه که پیاده سازی شده و اجازه اجرای داخلی تر ها رو نده.
Page2 متد Dispose رو تغییر نداده، پس متد Dispose والدش رو اجرا می کنه.
DefaultUserControl هم همینطور، پس متد Dispose والدش رو اجرا می کنه.
UserControl هم ظاهرا کدی برای Dispose نداره، پس متد Dispose والدش رو اجرا می کنه.
DefaultUserControl متد Dispose رو override کرده، پس هر کدی که در متد Dispose اش باشه همون اجرا میشه و البته در کدش base.Dispose رو هم فراخوانی کرده چون میخواد Dispose های والدین اش هم اجرا بشن.
اگر اون base.Dispose رو فراخوانی نمی کرد سلسله مراتب اجرا در همینجا قطع میشد و ادامه پیدا نمی کرد.
ScrollableControl متد Dispose رو تغییر نداده، پس متد Dispose والدش رو اجرا می کنه.
Control متد Dispose رو override کرده، پس هر کدی که در متد Dispose اش باشه همون اجرا میشه و البته در کدش base.Dispose رو هم فراخوانی کرده چون میخواد Dispose های والدین اش هم اجرا بشن.
Component ایجاد کننده متد Dispose ئه، یعنی آخرین حلقه این روال اجرا که متد Dispose اش اجرا میشه و یا میتونست اجرا بشه.
اگه شما در DefaultUserControl یا Page2 کدی برای Dispose می نوشتید و base.Dispose رو فراخوانی نمی کردید اجرا به Dispose ئه Component نمی رسید.

بله قابل استفاده هست . با خطا هم متوقف نشد و درست کار میکنه
Build اش هم روی x86 هه
یک چیزی در کدتون مشکل داره، یا کد به درستی قابل کامپایل نیست که Build کامل بشه، یا در پیاده سازی متد های سازنده اش یا Component اش یا کلاس های وابسته اش تغییری داده اید که دیگه در محیط Designer نمیشه روی فرم قرارش داد. شرایط محیط Designer با محیط بعد از اجرا تا حدودی فرق داره. یکسری موارد هست که برای کار در Designer مشکل ایجاد می کنه و باید رعایت کرد. بعضی هاشون رو راحت میشه فهمید ولی بعضی هاشون خیلی مستند نیستند. گاهی باگ های ویژوال استدیو هم دخیل ئه. گاهی لازمه ویژوال استدیو رو کامل ببنید و مجددا باز کنید تا تاثیر یک تغییر مهمی رو ببینید که با 10 بار Clean و Rebuild کردن پروژه هم مشاهده نمیشه.

مثلا من طبق تجربه میدونم که اگه بخوام یک کلاس جدید بسازم که در Designer قابل استفاده باشه، فرضا چیزی شبیه به DateTime بسازم که در UserControl ها در Property ها استفاده بشه، باید در Properties پروژه Assembly Version که چهار قسمت ئه، مقدار چهارم revision رو روی * قرار بدم، نه 0. تا ویژوال استدیو بفهمه که این Build کردن های مداوم رو نباید به حساب تغییر Assembly حساب کنه. چون Designer عادت داره از Assembly یک نسخه Cache در حافظه نگهداره. هر بار که پروژه کامپایل میشه یک Assembly جدید بوجود میاد که ظاهرش شاید کاملا مشابه قبلی ئه ولی صریحا اون نمونه باقی مونده در cache ئه Designer نیست. انگار که از یک پروژه یک کپی بگیرید، همه چیزشون شبیه همه ولی یکی نیستن. برای همین ممکنه پیغام خطای احمقانه ای بده که شیء از نوع Class1 قابل تبدیل به نوع Class1 نیست. دلیلش اینه که این Class1 اون Class1 نیست، یکی شون جدید ئه و یکی شون قدیمی. اینجا کد هیچ ایرادی نداره ولی دو تا اسمبلی متفاوت اند.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
دلیلش این که چند تا شی instance مجزا که نیستن که هربار یکی شون رو برگردونه ، یه instance بیشتر نیست. Instance اش با B سازگاره و B محسوب میشه ولی نوعش B نیست.


شما قبلا از متد Controls.Add استفاده کردین. پارامتر ورودی اش از چه نوعیه؟ Control ئه. نه Button و نه TextBox و نه هر نوع وراثت دیگه ای . پس چرا اونجا تعجب نمی کنین که پارامتر ورودی اش Control ئه اما روی فرم Button1 و TextBox1 و UserControl1 و ... به درستی قرار می گیره و تبدیل به Control خالی نمیشن؟ اگه شما این رو مبنا قرار می دیدن که چون this از نوع B ئه پس باید یک شیء با ماهیت B رو برگردونه و نباید از نوع C باشه پس باید براتون غیر قابل قبول باشه که Controls.Add یک Control رو دریافت کنه ولی روی فرم یک TextBox یا Button یا هر وارث دیگه ای از Control قرار بگیره.

اینم مثل همونه، مثل قضیه متغیر های object ئه. شما می توانید Button ها رو در object قرار بدید چون هر Button ای یک Object ئه، همانطور که هر Button ای یک Control ئه. ولی این به این معنی نیست که چون از object استفاده کردید دیگه رفتار اون شیء مثل دکمه ها نباشه و فرضا روی فرم نتونید قرارش بدید. همچنان یک Button ئه، چه در object قرارش بدید و چه در Control به هر حال یک دکمه است. this شبیه یک فیلد ئه که نوعش B باشه، حالا اگه داخلش یک شی از نوع C باشه همون شیء C رو بر می گردونه، وراثتش رو که حذف نمی کنه که بگیم باید تبدیل میشد به نوع B.
قواعد وراثت در #C به این شکل ئه، اگر غیر از این بود که شما نمی توانستید از Control.Add استفاده کنید.


عملا همه شون، ولی هر کدوم این اختیار رو داره که به داخلی تر ها اجازه اجرا بده یا نده. سلسله مراتبی میره عقب و اجرا میشن تا به متد Dispose ای برسه که پیاده سازی شده و اجازه اجرای داخلی تر ها رو نده.
Page2 متد Dispose رو تغییر نداده، پس متد Dispose والدش رو اجرا می کنه.
DefaultUserControl هم همینطور، پس متد Dispose والدش رو اجرا می کنه.
UserControl هم ظاهرا کدی برای Dispose نداره، پس متد Dispose والدش رو اجرا می کنه.
DefaultUserControl متد Dispose رو override کرده، پس هر کدی که در متد Dispose اش باشه همون اجرا میشه و البته در کدش base.Dispose رو هم فراخوانی کرده چون میخواد Dispose های والدین اش هم اجرا بشن.
اگر اون base.Dispose رو فراخوانی نمی کرد سلسله مراتب اجرا در همینجا قطع میشد و ادامه پیدا نمی کرد.
ScrollableControl متد Dispose رو تغییر نداده، پس متد Dispose والدش رو اجرا می کنه.
Control متد Dispose رو override کرده، پس هر کدی که در متد Dispose اش باشه همون اجرا میشه و البته در کدش base.Dispose رو هم فراخوانی کرده چون میخواد Dispose های والدین اش هم اجرا بشن.
Component ایجاد کننده متد Dispose ئه، یعنی آخرین حلقه این روال اجرا که متد Dispose اش اجرا میشه و یا میتونست اجرا بشه.
اگه شما در DefaultUserControl یا Page2 کدی برای Dispose می نوشتید و base.Dispose رو فراخوانی نمی کردید اجرا به Dispose ئه Component نمی رسید.


یک چیزی در کدتون مشکل داره، یا کد به درستی قابل کامپایل نیست که Build کامل بشه، یا در پیاده سازی متد های سازنده اش یا Component اش یا کلاس های وابسته اش تغییری داده اید که دیگه در محیط Designer نمیشه روی فرم قرارش داد. شرایط محیط Designer با محیط بعد از اجرا تا حدودی فرق داره. یکسری موارد هست که برای کار در Designer مشکل ایجاد می کنه و باید رعایت کرد. بعضی هاشون رو راحت میشه فهمید ولی بعضی هاشون خیلی مستند نیستند. گاهی باگ های ویژوال استدیو هم دخیل ئه. گاهی لازمه ویژوال استدیو رو کامل ببنید و مجددا باز کنید تا تاثیر یک تغییر مهمی رو ببینید که با 10 بار Clean و Rebuild کردن پروژه هم مشاهده نمیشه.

مثلا من طبق تجربه میدونم که اگه بخوام یک کلاس جدید بسازم که در Designer قابل استفاده باشه، فرضا چیزی شبیه به DateTime بسازم که در UserControl ها در Property ها استفاده بشه، باید در Properties پروژه Assembly Version که چهار قسمت ئه، مقدار چهارم revision رو روی * قرار بدم، نه 0. تا ویژوال استدیو بفهمه که این Build کردن های مداوم رو نباید به حساب تغییر Assembly حساب کنه. چون Designer عادت داره از Assembly یک نسخه Cache در حافظه نگهداره. هر بار که پروژه کامپایل میشه یک Assembly جدید بوجود میاد که ظاهرش شاید کاملا مشابه قبلی ئه ولی صریحا اون نمونه باقی مونده در cache ئه Designer نیست. انگار که از یک پروژه یک کپی بگیرید، همه چیزشون شبیه همه ولی یکی نیستن. برای همین ممکنه پیغام خطای احمقانه ای بده که شیء از نوع Class1 قابل تبدیل به نوع Class1 نیست. دلیلش اینه که این Class1 اون Class1 نیست، یکی شون جدید ئه و یکی شون قدیمی. اینجا کد هیچ ایرادی نداره ولی دو تا اسمبلی متفاوت اند.

ممنون
آها ببخشید درسته
مثلا کد زیر :

کد:
class C : B
    {
        public object Meth()
        {
            return "abc";
        }
    }

فراخونی شم :

کد:
C c = new C();
object d = c.Meth();
MessageBox.Show(d.GetType().ToString());

نوعش ، از نوع شی اش که رشته هست ، هست ولی توی object ریخته شده که برای استفاده باید تبدیل شه
اینو میدونستم . در واقع سئوالم یه چیز دیگه بود
اینکه پس زمانی که کلمه ی کلیدی this رو در کلاسی میگیم (در مثال تون ، در کلاس B) ، اگه شی ای که ساختیم ، از کلاس فرزند کلاسی که کلمه ی کلیدی this رو بکار بردیم بود (شی از کلاس C که ساخته بودین) ، کلمه ی کلیدی this ، در این صورت به اون شی کلاس فرزندش اشاره میکنه (شی ای از کلاس C اشاره میکنه) . درسته؟
درباره ی ToolBax هم ممنون .
 

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

بالا