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

SajjadKhati

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


کد:
if (e.KeyData == (Keys.Control | Keys.ControlKey))
            {
                MessageBox.Show("");
            }

شما گفته بودین که چون KeyData ، ترکیبی از کلیدهای فشرده شده رو ذخیره میکنه ، باید هر دو مقدار رو مثل بالا چک کرد
ولی اگه بخوایم بصورت ترکیبی با کلید A چک کنیم (Ctrl+A) ، پس چرا کد زیر مشکل داره؟ :


کد:
            if (e.KeyData == (Keys.Control | Keys.ControlKey | Keys.A))
            {
                MessageBox.Show("");
            }

و فقط بصورت زیر کار میکنه؟ :


کد:
            if (e.KeyData == (Keys.Control | Keys.A))
            {
                MessageBox.Show("");
            }

مشکل کد دوم کجاست؟
کد زیر :


کد:
            if ((e.KeyData == (Keys.Control | Keys.ControlKey)) & e.KeyCode == Keys.A)
            {
                MessageBox.Show("");
            }

هم بخاطر این کار نمیکنه که وقتی کلید control فشرده میشه ، داخل e.KeyCode ، مقدار Keys.Control قرار میگیره و دیگه منتظر فشرده شدن دکمه ی A نمیمونه که مقدارش برابر Keys.A بشه؟
 

the_king

مدیرکل انجمن
سلام
ممنون
استاد علی ، در رویداد KeyDown فرم ، همونطور که در پست های قبل بررسی کردیم ، کد زیر مشکلی نداره :


کد:
if (e.KeyData == (Keys.Control | Keys.ControlKey))
            {
                MessageBox.Show("");
            }

شما گفته بودین که چون KeyData ، ترکیبی از کلیدهای فشرده شده رو ذخیره میکنه ، باید هر دو مقدار رو مثل بالا چک کرد
ولی اگه بخوایم بصورت ترکیبی با کلید A چک کنیم (Ctrl+A) ، پس چرا کد زیر مشکل داره؟ :


کد:
            if (e.KeyData == (Keys.Control | Keys.ControlKey | Keys.A))
            {
                MessageBox.Show("");
            }

و فقط بصورت زیر کار میکنه؟ :


کد:
            if (e.KeyData == (Keys.Control | Keys.A))
            {
                MessageBox.Show("");
            }
مشکل کد دوم کجاست؟
یک موردی رو انگاری فراموش کردید، یادتون باشه در این مورد صحبت کردیم که تعداد کلید ها زیاده و در یک متغیر 32 بیتی برای هر کلید یک بیت مجزا در نظر نگرفته اند. به همین جهت هم کد کلید ها نمیتونه با هم | بشه و هر بار صرفا کد یک کلید مشخص میشه، نه چند کلید همزمان. یادتون هست؟ اون Control کد کلید نیست، کد Mask کلید ئه و فقط هم برای چند کلید خاص Mask داریم. وقتی A رو فشار دادید رخداد فشار کلید A ئه که اجرا میشه، دیگه همراهش ControlKey وجود نداره. ControlKey در یک رخداد قبلی اجرا شده و رفته پی کارش. حالا از روی اون Mask ئه که میشه فهمید همراه این A کدوم کلید های کنترلی فشار داده شده اند.


کد زیر :

کد:
            if ((e.KeyData == (Keys.Control | Keys.ControlKey)) & e.KeyCode == Keys.A)
            {
                MessageBox.Show("");
            }

هم بخاطر این کار نمیکنه که وقتی کلید control فشرده میشه ، داخل e.KeyCode ، مقدار Keys.Control قرار میگیره و دیگه منتظر فشرده شدن دکمه ی A نمیمونه که مقدارش برابر Keys.A بشه؟
کلا یک کلید داخل KeyCode قرار می گیره که بخاطر فشرده شدنش رخداد اجرا شده. کاری به کلید های قبلی و بعدی نداره. شما صرفا از روی KeyCode نمی توانید بفهمید که همراهش چه کلید های دیگری از قبل فشرده شده.
KeyData کامله و مشخص می کنه که چه کلیدی الان فشرده شد و همراهش چه Mask کلید هایی فشرده شده هستند.
وقتی Control رو فشار می دهید در KeyCode فقط ControlKey قرار داره و در KeyData مقدار ControlKey | Control چون بجز ControlKey مقدار Mask اش (Control) هم هست.
وقتی A رو در همون حالت فشرده بودن Control فشار می دهید در KeyCode فقط A قرار داره که الان فشرده شد و اصلا کاری به Control که از قبل فشرده شده بوده نداره و در KeyData مقدار A | Control یعنی کلید A به علاوه Mask ئه Control
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
یک موردی رو انگاری فراموش کردید، یادتون باشه در این مورد صحبت کردیم که تعداد کلید ها زیاده و در یک متغیر 32 بیتی برای هر کلید یک بیت مجزا در نظر نگرفته اند. به همین جهت هم کد کلید ها نمیتونه با هم | بشه و هر بار صرفا کد یک کلید مشخص میشه، نه چند کلید همزمان. یادتون هست؟ اون Control کد کلید نیست، کد Mask کلید ئه و فقط هم برای چند کلید خاص Mask داریم. وقتی A رو فشار دادید رخداد فشار کلید A ئه که اجرا میشه، دیگه همراهش ControlKey وجود نداره. ControlKey در یک رخداد قبلی اجرا شده و رفته پی کارش. حالا از روی اون Mask ئه که میشه فهمید همراه این A کدوم کلید های کنترلی فشار داده شده اند.
ممنون
کلا در حال بررسی سئوال ها و جواب هایی که در این تاپیک دادین ، هستم . چون بعضی چیزها رو فراموش کردم . الان صفحه ی 5 ام
من دقیقا متوجه نشدم کلا .
کد Mask چیه؟



کلا یک کلید داخل KeyCode قرار می گیره که بخاطر فشرده شدنش رخداد اجرا شده. کاری به کلید های قبلی و بعدی نداره. شما صرفا از روی KeyCode نمی توانید بفهمید که همراهش چه کلید های دیگری از قبل فشرده شده.
KeyData کامله و مشخص می کنه که چه کلیدی الان فشرده شد و همراهش چه Mask کلید هایی فشرده شده هستند.
وقتی Control رو فشار می دهید در KeyCode فقط ControlKey قرار داره و در KeyData مقدار ControlKey | Control چون بجز ControlKey مقدار Mask اش (Control) هم هست.
وقتی A رو در همون حالت فشرده بودن Control فشار می دهید در KeyCode فقط A قرار داره که الان فشرده شد و اصلا کاری به Control که از قبل فشرده شده بوده نداره و در KeyData مقدار A | Control یعنی کلید A به علاوه Mask ئه Control

آها ممنون
پس داخل KeyCode ، آخرین کلید فشرده شده و فقط یک کلید قرار میگیره بنابراین عملگر | رو قبول نمیکنه (البته این یادم بود)
 

the_king

مدیرکل انجمن
ممنون
کلا در حال بررسی سئوال ها و جواب هایی که در این تاپیک دادین ، هستم . چون بعضی چیزها رو فراموش کردم . الان صفحه ی 5 ام
من دقیقا متوجه نشدم کلا .
کد Mask چیه؟
Mask یک مقدار ئه که توش یک یا چند بیت که مهمه 1 ئه و بقیه که برای Mask مهم نیستند 0 ئه. این Mask رو با هر مقداری AND کنید اون بیت های موثر میمونه و بقیه 0 میشه.
کاربردش اینه که یک مقداری هست که فرضا 32 بیتی ئه، اما میخوان داخلش چند تا مورد رو ترکیبی ذخیره کنند. برای همین فضای بیتی اش رو تقسیم می کنند، یک قسمتی از فضای بیتی رو که حتی میتونه یک بیت باشه، جدا می کنند برای یک مورد خاص، مثلا میگن از بیت یکم تا بیت چهارم مربوط به یک چیزیه، بیت های بعدی مربوط به چیز دیگری. در مورد کد کلید ها همین حالت هست، از یک طرف KeyData داره کد کلید رو مشخص می کنه و از طرف دیگه در کنارش کد کلیدی های کنترلی رو که همزمان فشرده شدند. هر کدوم از کلید های کنترلی یک Mask مشخص داره، مثلا 00001000 یک Mask ای ئه برای بیت چهارم. شما عملا وقتی دارید چک می کنید که کلید Ctrl فشرده شده یا خیر، دارید Mask ئه Control رو با مقدار AND می کنید تا ببینید اون بیت خاص مربوط به Control الان 1 ئه یا 0
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
Mask یک مقدار ئه که توش یک یا چند بیت که مهمه 1 ئه و بقیه که برای Mask مهم نیستند 0 ئه. این Mask رو با هر مقداری AND کنید اون بیت های موثر میمونه و بقیه 0 میشه.
کاربردش اینه که یک مقداری هست که فرضا 32 بیتی ئه، اما میخوان داخلش چند تا مورد رو ترکیبی ذخیره کنند. برای همین فضای بیتی اش رو تقسیم می کنند، یک قسمتی از فضای بیتی رو که حتی میتونه یک بیت باشه، جدا می کنند برای یک مورد خاص، مثلا میگن از بیت یکم تا بیت چهارم مربوط به یک چیزیه، بیت های بعدی مربوط به چیز دیگری. در مورد کد کلید ها همین حالت هست، از یک طرف KeyData داره کد کلید رو مشخص می کنه و از طرف دیگه در کنارش کد کلیدی های کنترلی رو که همزمان فشرده شدند. هر کدوم از کلید های کنترلی یک Mask مشخص داره، مثلا 00001000 یک Mask ای ئه برای بیت چهارم. شما عملا وقتی دارید چک می کنید که کلید Ctrl فشرده شده یا خیر، دارید Mask ئه Control رو با مقدار AND می کنید تا ببینید اون بیت خاص مربوط به Control الان 1 ئه یا 0

ممنون استاد علی
ولی من بازم قشنگ متوجه نشدم مطالب Mask رو:green:
اصلا چرا چیزی به عنوان کدهای Mask باید باشه؟ چرا برای چک کردن اینکه KeyData حاوی مقداری هست که آیا دکمه ی کنترل فشرده شد یا نه ، چرا چک کردن کلیدها و مقادیر کلیدها کفایت نمیکنه؟ یعنی چرا کفایت نمیکنه که چک بشه مقدار KeyData برابر ControlKey هست یا نه؟
باز اینجا آدم گیج میشن که اگه بخوایم چک کنیم که دکمه ی کنترل به تنهایی فشرده شده هست ، باید مقدار کلید کنترل و مقدار Mask کنترل رو با هم چک کنیم اما وقتی کلیدی ترکیبی Ctrl+A رو بخوایم چک کنیم ، دیگه مقدار Mask کنترل رو نباید چک و ترکیب کنیم!!
 

the_king

مدیرکل انجمن
ممنون استاد علی
ولی من بازم قشنگ متوجه نشدم مطالب Mask رو:green:
اصلا چرا چیزی به عنوان کدهای Mask باید باشه؟ چرا برای چک کردن اینکه KeyData حاوی مقداری هست که آیا دکمه ی کنترل فشرده شد یا نه ، چرا چک کردن کلیدها و مقادیر کلیدها کفایت نمیکنه؟ یعنی چرا کفایت نمیکنه که چک بشه مقدار KeyData برابر ControlKey هست یا نه؟
فرض کنیم چیزی به نام Mask نداریم و روش شما هم قابل استفاده است :
اگر KeyData برابر ControlKey باشه با فرض شما معنی اش اینه که فقط کلید Ctrl فشرده شده و هیچ کلید دیگری هم فشرده نشده.
اگر KeyData برابر A باشه، با فرض شما معنی اش اینه که فقط کلید A فشرده شده و هیچ کلید دیگری هم فشرده نشده.
با فرض شما KeyData برابر مقادیر ترکیبی هم نمیتونه باشه یعنی ترکیب چند کلید رو نمیتونه اعلام کنه، چرا؟ چون تعداد کلید ها اونقدر زیاده که مقدار حاصل ترکیب ممکنه خودش کد یک کلید دیگه باشه و نشه دو حالت رو از هم تشخیص شون داد.


باز اینجا آدم گیج میشن که اگه بخوایم چک کنیم که دکمه ی کنترل به تنهایی فشرده شده هست ، باید مقدار کلید کنترل و مقدار Mask کنترل رو با هم چک کنیم اما وقتی کلیدی ترکیبی Ctrl+A رو بخوایم چک کنیم ، دیگه مقدار Mask کنترل رو نباید چک و ترکیب کنیم!!
پس شما چه فرقی بین فشردن A و Ctrl + A و Shift + A و Ctrl + Shift + A و Alt + A و Ctrl + Alt + A و Shift + Alt + A و Shift + Ctrl + Alt + A قائل شدید؟ در همه اینها A فشرده شده.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
اینکه نمی توانید Location.X رو تغییر دهید مقصر خود button12 یا X یا Location نیست. دلیلش این است Point که Location از نوع آن است یک ساختار است، struct ئه، نه کلاس.
یک تفاوت اساسی میان struct و class این است که کلاس ها reference type اند و struct ها value type اند. به عبارت ساده یعنی اگر مقدار یک شیء کلاس را از یک متغیر در متغیر دیگری کپی کنید
همان شیء را در متغیر مقصد خواهید داشت، ولی اگر شیء ساختار را کپی کنید یک نسخه جدید ولی با مقادیر مشابه قبلی ساخته می شود.
وقتی مقدار Location را از button12 می خوانید به شما یک کپی از آن شی Point تحویل داده می شود نه خودش. کامپایلر برای این خطا می گیرد که شما متوجه این نکته باشید که شما دارید X یک نسخه کپی را عوض می کنید
که جایی هم ثبت نمی شود و و ربطی به Location ندارد.

یا Left را عوض کنید که همان مقدار X را تغییر می دهد و یا یک Point به Location تحویل بدهید :
کد:
            button1.Left = 150;
کد:
            button1.Location = new Point(150, button1.Top);
کد:
            button1.Location = new Point(150, button1.Location.Y);

استاد علی ، این رو در صفحه ی 5 گفته بودین
من دقیق متوجه نشدم
موقع خوندن از استراکچر هم مگه کپی میکنه؟!! مگه موقع قرار دادن شی موجود به اعضای استراکچر ، کپی نمیکنه فقط؟
پس چرا در کد زیر ، وقتی اعضای استراکچر رو بعد از ساختن شی ، تغییر میدیم ، مثل پروپرتی X در استراکچر point ، کمپایلر ارور نمیده که داره کپی میکنه و مقدار قبلی هه ، در یه حافظه ی دیگه هست؟ :

کد:
        public struct TestStruct
        {
            public int X { get; set; }
            public int Y { get; set; }
            public TestStruct(string a)
            {
                this.X = 10;
                this.Y = 20;
            }
        }

و ایجاد شی :

کد:
        private void btnTest_Click(object sender, EventArgs e)
        {
            Page2Class.TestStruct myStruct = new Page2Class.TestStruct();
            myStruct.X = 4;

            MessageBox.Show(myStruct.X.ToString());
        }
پس چرا در کد myStruct.X = 4; مثل بالا کمپایلر خطا نگرفت؟ هر دو ، مقداردهی جدید برای عضو استراکچر بودن
----------------
بعد اینکه چرا فیلدها و پروپرتی های استراکچر ، حتما باید مقداردهی بشن در متد سازنده؟
بعد هم چرا متد سازنده ، حتما باید یه پارامتر دریافت کنه؟ حتی اگه استفاده نشه؟


فرض کنیم چیزی به نام Mask نداریم و روش شما هم قابل استفاده است :
اگر KeyData برابر ControlKey باشه با فرض شما معنی اش اینه که فقط کلید Ctrl فشرده شده و هیچ کلید دیگری هم فشرده نشده.
اگر KeyData برابر A باشه، با فرض شما معنی اش اینه که فقط کلید A فشرده شده و هیچ کلید دیگری هم فشرده نشده.
بله درسته

با فرض شما KeyData برابر مقادیر ترکیبی هم نمیتونه باشه یعنی ترکیب چند کلید رو نمیتونه اعلام کنه، چرا؟ چون تعداد کلید ها اونقدر زیاده که مقدار حاصل ترکیب ممکنه خودش کد یک کلید دیگه باشه و نشه دو حالت رو از هم تشخیص شون داد.
نه
من enum ای رو چک کردم که روند اعدادش بصورت باینری بود یعنی 0 و 1 و 2 و 4 و 8 و 16 و 32 و 64 و 128 و 256 و 1024 و ... و کلا ضریب 2 بود . در این حالت ، تا جایی که تست کردم ، هیچ وقت حاصل ترکیب و اور | کردن اعداد ، برابر با مقدار موجود نشد . نمیدونم مایکروسافت چرا بصورت باینری اعداد کلیدها رو نچید (البته قبلا گفتین ولی دلیل شو فراموش کردم) . به هر حال این جوری خیلی راحت تر بود.


پس شما چه فرقی بین فشردن A و Ctrl + A و Shift + A و Ctrl + Shift + A و Alt + A و Ctrl + Alt + A و Shift + Alt + A و Shift + Ctrl + Alt + A قائل شدید؟ در همه اینها A فشرده شده.

دقیقا متوجه منظورتون نشدم
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
یک لحظه فکر کنید که Location و Point رو نمی شناسید و خودتان می خواهید یک کد Property بنویسید که مختصات یک نقطه رو بخونه و یا بنویسه.
اول باید نقطه رو تعریف کنید، دو تا گزینه دارید، نقطه رو یا با کلاس تعریف می کنید و یا با ساختار.
کد:
    class PointClass
    {
        public int X;
        public int Y;
    }
کد:
    public struct PointStruct
    {
        public int X;
        public int Y;
    }
مساله سر فرق اساسی ایندو تا است، کلاس همیشه با ارجاع کار می کنه و ساختار همیشه با مقدار.
کد:
            var p1 = new PointStruct();
            p1.X = 4;
            var p2 = p1;
            p2.X = 12;
مقدار p1.X همان 4 ای که در سطر دوم می نویسید می ماند و 12 نمی شود، چون var p2 = p1 یک کپی جدید از مقدار p1 را در p2 می نویسد، به همان شیء p1 ارجاع نمی دهد، مستقل از p1 است.

کد:
            var c1 = new PointClass();
            c1.X = 4;
            var c2 = c1;
            c2.X = 12;
مقدار c1.X در انتها 12 ای می شود که در c2 نوشته شده، چون var c2 = c1 به c1 ارجاع می دهد، یک کپی جدید از شی c1 را در c2 نمی نویسد. هر کاری که با c2 انجام می دهید روی c1 انجام داده اید.

حالا شما نقطه رو به یکی از دو روش تعریف کرده اید و می توانید مشخصه ای مثل Location رو بنویسید،
کد:
        public PointClass Location
        {
            get;
            set;
        }
کد:
        public PointStruct Location
        {
            get;
            set;
        }
برای کد Location ظاهرا فقط نوع داده عوض می شود، ولی ماهیت کارش بستگی به این دارد که برای تعریف کردن نقطه از struct استفاده کرده باشید یا class
اگر از struct استفاده کرده باشید Location شما مشابه همان var p2 = p1 یک کپی جدید از نقطه را بر می گرداند، شما Location.X رو عوض می کنید، ولی این X یک کپی است،
مقدار نقطه ای که return شده همچنان همان مقدار قبلی می ماند
. برای همین است که ;button1.Location.X = 100 اشکال دارد، شما با button1.Location فقط کپی دریافت می کنید.
هر بلایی که سر کپی مقدار بیاورید روی شیء اصلی تاثیری ندارد. و مهم اینجا است که System.Drawing.Point یک struct است، نه class

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


کد:
MessageBox.Show(myStruct.X.ToString());

رو مینویسیم ، آخرین مقداری که بهش داده شد که 4 هست رو برمیگردونه (نه مقدار 10 ای که قبلا داده بودیم)
----------------------
به هر حال من دلیل اینکه چرا کمپایلر Location.X رو نمیذاره مقداردهی کنیم رو هنوز متوجه نشدم
 

the_king

مدیرکل انجمن
استاد علی ، این رو در صفحه ی 5 گفته بودین
من دقیق متوجه نشدم
موقع خوندن از استراکچر هم مگه کپی میکنه؟!! مگه موقع قرار دادن شی موجود به اعضای استراکچر ، کپی نمیکنه فقط؟

فرض کنیم شما یک struct دارید به نام Point که اعضاء اش X و Y باشند. اگه شما یک متغیر به اسم loc از نوع Point داشته باشید، مقدار loc.X رو می توانید خیلی راحت عوض کنید، چه از داخل کلاس و چه از بیرونش، چه با تابع و چه با Property، اما فرض کنیم که شما یک Property هم به اسم Location دارید که مقدار loc رو return می کنه و مقدار loc رو می نویسه. اگر loc یک Class بود، اینجا Location می توانست معادل loc باشه، چون ارجاع به شیء بود، اما چون struct ئه، دیگه Location معادل loc نیست، کپی مقدار Loc ئه، وقتی شما می نویسید Location.X = 12 اول باید مقدار Location رو بخونه، return loc انجام میشه تا این مقدار از Location خونده بشه. از اونجایی که loc یک struct ئه، return loc هم از نوع Value Type ئه، خود loc رو تحویل نمیده، ارجاع به شیء نیست، یک کپی از مقدار loc رو return می کنه، نه خود loc. شما دارید مقدار X اون Point که بر گردونده میشه و کپی ئه رو 12 می کنید، نه مقدار loc.X . برای همین کامپایلر خطا می گیره که کاری که می کنیذ چیزی نیست که میخواهید. شما از طریق Location نمی توانید مقدار اعضاء loc رو عوض کنید، اما می توانید با ... = Location خودشو یکجا با یک Point دیگه تعویض کنید.
بعد اینکه چرا فیلدها و پروپرتی های استراکچر ، حتما باید مقداردهی بشن در متد سازنده؟

نه، Value Type ئه، مقدار پیشفرض داره، struct ها یک متد سازنده بدون پارامتر دارند که به همه فیلد هاشون مقدار پیشفرض میده.

بعد هم چرا متد سازنده ، حتما باید یه پارامتر دریافت کنه؟ حتی اگه استفاده نشه؟
چون متد سازنده بدون پارامترش کارش کاملا مشخصه و تغییر ناپذیر. شما از لحظه ای که struct رو تعریف کردید مقدار پیشفرض داره، مثل ;int i میمونه.

من enum ای رو چک کردم که روند اعدادش بصورت باینری بود یعنی 0 و 1 و 2 و 4 و 8 و 16 و 32 و 64 و 128 و 256 و 1024 و ... و کلا ضریب 2 بود . در این حالت ، تا جایی که تست کردم ، هیچ وقت حاصل ترکیب و اور | کردن اعداد ، برابر با مقدار موجود نشد . نمیدونم مایکروسافت چرا بصورت باینری اعداد کلیدها رو نچید (البته قبلا گفتین ولی دلیل شو فراموش کردم) . به هر حال این جوری خیلی راحت تر بود.
اشتباه چک کردید. آخه مگه میشه توی صفحه کلیدی که این همه کلید داره برای هر کلید یک بیت در نظر گرفت؟ فقط چند تا کلید Mask انتهای enum اونطور حالتی دارند.
Keys.png

دقیقا متوجه منظورتون نشدم
شما نمی توانید چک کنید که Ctrl + A فشرده شده یا خیر، مگر اینکه چک کنید Ctrl فشرده شده و بجز Ctrl کلید کنترلی دیگه ای فشرده نشده. اگر قرار باشه Mask ها کنترلی رو حذف کنیم با چی چک اش می کنید؟
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
فرض کنیم شما یک struct دارید به نام Point که اعضاء اش X و Y باشند. اگه شما یک متغیر به اسم loc از نوع Point داشته باشید، مقدار loc.X رو می توانید خیلی راحت عوض کنید، چه از داخل کلاس و چه از بیرونش، چه با تابع و چه با Property، اما فرض کنیم که شما یک Property هم به اسم Location دارید که مقدار loc رو return می کنه و مقدار loc رو می نویسه. اگر loc یک Class بود، اینجا Location می توانست معادل loc باشه، چون ارجاع به شیء بود، اما چون struct ئه، دیگه Location معادل loc نیست، کپی مقدار Loc ئه، وقتی شما می نویسید Location.X = 12 اول باید مقدار Location رو بخونه، return loc انجام میشه تا این مقدار از Location خونده بشه. از اونجایی که loc یک struct ئه، return loc هم از نوع Value Type ئه، خود loc رو تحویل نمیده، ارجاع به شیء نیست، یک کپی از مقدار loc رو return می کنه، نه خود loc. شما دارید مقدار X اون Point که بر گردونده میشه و کپی ئه رو 12 می کنید، نه مقدار loc.X . برای همین کامپایلر خطا می گیره که کاری که می کنیذ چیزی نیست که میخواهید. شما از طریق Location نمی توانید مقدار اعضاء loc رو عوض کنید، اما می توانید با ... = Location خودشو یکجا با یک Point دیگه تعویض کنید.
ممنون استاد علی
پس با این اوصاف ، در کد زیر :

کد:
        public struct TestStruct
        {
            public int X { get; set; }
            public int Y { get; set; }
            public TestStruct(string a)
            {
                this.X = 10;
                this.Y = 20;
            }
        }
و در رویدادی در فرم1 :
کد:
        public Page2Class.TestStruct loc = new Page2Class.TestStruct();
        public Page2Class.TestStruct Location
        {
            get
            {
                return this.loc;
            }
            set
            {
                this.loc = value;
            }
        }

        public Page2Class.TestStruct loc_2;

        private void btnStruct1_Click(object sender, EventArgs e)
        {
            this.loc_2 = this.loc;
            this.loc_2.X = 7;

            MessageBox.Show(this.loc_2.X.ToString());
        }
باید همین ارور رو بده اما چرا نمیده؟ چون در متغییرloc_2 ، مثل پروپرتی ای که گفتین ، مقدار loc ریخته شد و بعد هم عضو X از loc_2 رو تغییر و بعد هم خوند
اما در پروپرتی در کد زیر که دقیقا همین کار رو میکنه ، ارور میده !! چرا؟!! آخه مقدار این پروپرتی هم از متغییر loc خونده و نوشته میشه و بعد عضو X از پروپرتی Location رو تغییر و فراخونی کرد :

کد:
        public Page2Class.TestStruct loc = new Page2Class.TestStruct();
        public Page2Class.TestStruct Location
        {
            get
            {
                return this.loc;
            }
            set
            {
                this.loc = value;
            }
        }

        public Page2Class.TestStruct loc_2;

        private void btnStruct1_Click(object sender, EventArgs e)
        {
            this.loc.X = 4;
            this.Location.X = 2;
          

            MessageBox.Show(this.loc.X.ToString());
        }
هر دو که یک کار رو میکنن ، پس چرا یکی ارور میده و اون یکی نه؟!

چون متد سازنده بدون پارامترش کارش کاملا مشخصه و تغییر ناپذیر. شما از لحظه ای که struct رو تعریف کردید مقدار پیشفرض داره، مثل ;int i میمونه.
مثلا طرف بخواد پارامتر توی متد سازنده نگیره و به همه ی فیلدها و پروپرتی ها ، شی جدیدی داخل متد سازنده بده

اشتباه چک کردید. آخه مگه میشه توی صفحه کلیدی که این همه کلید داره برای هر کلید یک بیت در نظر گرفت؟ فقط چند تا کلید Mask انتهای enum اونطور حالتی دارند.
Keys.png


شما نمی توانید چک کنید که Ctrl + A فشرده شده یا خیر، مگر اینکه چک کنید Ctrl فشرده شده و بجز Ctrl کلید کنترلی دیگه ای فشرده نشده. اگر قرار باشه Mask ها کنترلی رو حذف کنیم با چی چک اش می کنید؟

مثلا در این حالتی که اعداد ، ضریب 2 هستند ، میشه دو عدد بگین که حاصل اور شدن شون برابر یه عدد موجود بشه؟
من کلا قضیه ی Mask رو دقیق متوجه نشدم که چرا توی KeyData ، اگه کنترل رو به تنهایی مد نظرمون باشه ، باید هم مقدار کلید و هم مقدار mask اش رو با هم اور کنیم ولی وقتی دکمه ی ترکیبی میشه ، مقدار Mask رو نباید چک و اور کنیم!
ممنون :rose:
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
اون لیست ای که با ()new ArrayList می سازید خالیه، برای همین آیتم [myArrList[i وجود نداره که بخواهید مقداری داخلش قرار بدهید.
کد:
            ArrayList myArrList = new ArrayList() { "ali", "hasan", "mahmood" };

کد:
            ArrayList myArrList = new ArrayList(myArray);

کد:
            ArrayList myArrList = new ArrayList();
            myArrList.AddRange(myArray);

ممنون استاد علی
این رو توی صفحه ی 7 جواب دادین
اول اینکه بگم ، ببخشید این روزا سئوالات زیاد میپرسم ، چون دارم پست های قبلی رو مرور میکنم و اون موقع بصورت کامل متوجه نشدم رو الان میپرسم
---------------------------
آها وقتی هیچ آرگومانی نمیدیم ، خالی هه
خوب خالی باشه . دیگه مقدار قرار دادن توی یک شی arraylist فکر نکنم ربطی به خالی بودنش داشته باشه؟ اگه به خالی بودنش ربط داره ، الان در همین کد پس چطور با متد arraylist.Add اش میشه پرش کرد؟! وگرنه با متد add اش هم نباید پر شه
جور دیگه ای بهتره بگم . اینکه اولا مثل آرایه ها ، arraylist هم باید تعداد اعضای آرایه هاشون مشخص باشه تا مقدار بهش داد و ارور ArgumentOutOfRange رو نده؟ اگه آره ، پس چرا پروپرتی Capacity رو که مقداردهی میکنیم ، که طبعا باید تعداد اعضاش رو مشخص کنه و در خط بعد با روش ایندکس گذاری ، مقداردهی میکنیم ، باز هم ارور میده؟ یعنی چرا این هم ارور میده؟:

کد:
ArrayList a = new ArrayList(3);
a[0] = "abc";
و دوما وقتی حتی پروپرتی Capacity شو مقداردهی نمیکنیم ، پس چرا با متد add ، مقداردهی میشه و ارور ArgumentOutOfRange رو نمیده ؟ البته اگه مشکل از مشخص نکردن طول arraylist هست وگرنه اگه نیست ، پس چرا با روش ایندکس گذاری که مقداردهی انجام میشه ، ارور میده؟
کلا میشه با روش ایندکس گذاری مقداردهی کرد arraylist رو؟ اگه آره ، یه مثال میزنین؟
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
Brush یک کلاس پایه است، برای این تعریف شده که اغلب متد هایی که با Brush کار می کنند با هر نوع Brush ای قابل استفاده هستند.
چیزی که شما می سازید معمولا SolidBrush و TextureBrush و HatchBrush و ... است.
کد:
            var myBrush = new SolidBrush(Color.Red);
            e.Graphics.DrawLine(new Pen(myBrush), 0, 0, 100, 100);

کد:
            var myBrush = new TextureBrush(SystemIcons.Error.ToBitmap());
            e.Graphics.DrawLine(new Pen(myBrush, SystemIcons.Error.Width), 0, 0, 100, 100);

کد:
            var myBrush = new System.Drawing.Drawing2D.HatchBrush(System.Drawing.Drawing2D.HatchStyle.ZigZag, Color.Blue, BackColor);
            e.Graphics.DrawLine(new Pen(myBrush, 10f), 0, 0, 100, 100);

ممنون
این سئوال در صفحه ی 8 ، جواب دادین
این ربطی به Brush نداره : اول اینکه چرا کلاس System.Drawing.SystemBrushes رو نمیشه ازش شی ساخت؟ ظاهرا متد سازنده نداره ، پس باید متد سازنده ی پیش فرض داشته باشه و باید بشه ازش شی ساخت
ولی تمام اعضاش public static هستن ولی جای تعجب اینه که بعد از گذاشتن نقطه ، بعد از System.Drawing.SystemBrushes ، هیچ عضوش رو نمیاره !
-----------------
ولی سئوال مهم اینه که چرا وقتی شی picturebox میسازیم ، در رویداد paint اش که کد زیر رو مینویسیم ، هیچ شکلی رو توی picturebox نمیکشه؟ ولی برای بقیه ی کنترل ها مثل usercontrol و form ، مشکلی نداره :


کد:
private void picBoxPaint_Paint(object sender, PaintEventArgs e)
        {
            Graphics picBoxGraphics = this.picBoxPaint.CreateGraphics();
            Brush drawBrush = new SolidBrush(Color.Pink);
            picBoxGraphics.DrawString("salam", new Font("Arial", 15), drawBrush, new PointF(30, 10));

        }
 
آخرین ویرایش:

the_king

مدیرکل انجمن
ممنون استاد علی
پس با این اوصاف ، در کد زیر :

کد:
        public struct TestStruct
        {
            public int X { get; set; }
            public int Y { get; set; }
            public TestStruct(string a)
            {
                this.X = 10;
                this.Y = 20;
            }
        }
و در رویدادی در فرم1 :
کد:
        public Page2Class.TestStruct loc = new Page2Class.TestStruct();
        public Page2Class.TestStruct Location
        {
            get
            {
                return this.loc;
            }
            set
            {
                this.loc = value;
            }
        }

        public Page2Class.TestStruct loc_2;

        private void btnStruct1_Click(object sender, EventArgs e)
        {
            this.loc_2 = this.loc;
            this.loc_2.X = 7;

            MessageBox.Show(this.loc_2.X.ToString());
        }

باید همین ارور رو بده اما چرا نمیده؟ چون در متغییرloc_2 ، مثل پروپرتی ای که گفتین ، مقدار loc ریخته شد و بعد هم عضو X از loc_2 رو تغییر و بعد هم خوند
اما در پروپرتی در کد زیر که دقیقا همین کار رو میکنه ، ارور میده !! چرا؟!!


شما یک متغیر تعریف کردید به نام loc_2 و بهش میگید این مثل پروپرتی ئه که من مثال زدم. شما کجای کدتون this.Location.X = 7 دارید؟ Variable و Property دو تا موجودیت جدا هستند، از نظر شما متغیر همون پروپرتی ئه؟ شما تو کدتون می نویسید this.loc_2.X = 7 و مستقیما مقدار داخل فیلد ها و پروپرتی های متغیر رو تغییر می دهید و از هیچ Property ای هم استفاده نمی کنید، با اصرار کردن که نمیشه چیزی که شبیه مثال دیگه ای نیست یکی فرض کرد.
آخه مقدار این پروپرتی هم از متغییر loc خونده و نوشته میشه و بعد عضو X از پروپرتی Location رو تغییر و فراخونی کرد :
کد:
        public Page2Class.TestStruct loc = new Page2Class.TestStruct();
        public Page2Class.TestStruct Location
        {
            get
            {
                return this.loc;
            }
            set
            {
                this.loc = value;
            }
        }

        public Page2Class.TestStruct loc_2;

        private void btnStruct1_Click(object sender, EventArgs e)
        {
            this.loc.X = 4;
            this.Location.X = 2;
         

            MessageBox.Show(this.loc.X.ToString());
        }
هر دو که یک کار رو میکنن ، پس چرا یکی ارور میده و اون یکی نه؟!
هر دو چطور یه کار رو می کنند؟ اگر یک کار رو می کنند پس متغیر چیز بیخودیه و نباید باشه. یکبار یک کاغذ به نام loc رو بر میدارید رو در کادر X اش می نویسید 4. یکبار هم اول از این کاغذ کپی می گیرید و داخل کادر X اون کاغذ کپی می نویسید 2. این دو تا کاغذ یکی هستند؟ شما هر بلایی سر کاغذ کپی بیارید هیچ ربطی به کاغذ اول نداره. this.Location که this.loc نیست، یک کپی از مقدار this.loc ئه. مفهوم کپی که نیاز به توضیح دادن نداره :
کد:
        private Point _loc;

        public Point Loc
        {
            get
            {
                return _loc;
            }
            set
            {
                _loc = value;
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            _loc = new Point(0, 0);
            var a = _loc;
            a.X = 1;
            var b = a;
            b.Y = 2;
            var c = _loc;
            c.X = 3;
            var d = Loc;
            d.Y = 4;
            MessageBox.Show(string.Format("_loc={0} a={1} b={2} c={3} d={4}", _loc, a, b, c, d));
        }

مثلا طرف بخواد پارامتر توی متد سازنده نگیره و به همه ی فیلدها و پروپرتی ها ، شی جدیدی داخل متد سازنده بده
شی جدید یعنی شیء متفاوت. تفاوت بین ()new Button و ()new Button چیه؟ تفاوت شون اینه که یک شیء واحد نیستند. مقدار فیلد هاشون هم کاملا یکسان باشه خودشون شیء واحدی نیستند. اما struct ها Value Type اند، تفاوتی بین ()new Point و ()new Point نیست و نبایدم باشه. متد سازنده ای که شما می خواهید عملا میخواد همچین ساختاری رو بهم بزنه، بگه ()Point برابر ()Point نیست، چون این یک شیء ئه با مقادیری و اون یک شیء دیگری با مقادیر دیگه ای. چنین چیزی برای Value Type ها اصلا معنی نداره، اینها Reference Type نیستند.

مثلا در این حالتی که اعداد ، ضریب 2 هستند ، میشه دو عدد بگین که حاصل اور شدن شون برابر یه عدد موجود بشه؟
2 و 4 و 6 و 8 و 10 و 12 همه شون ضریب 2 هستند، 4 | 2 برابر 6 ئه، 2 | 6 برابر 6 ئه (یعنی اصلا 2 | 6 رو نمیشه از 6 تفکیک کرد)، 2 | 8 برابر 10 ئه و ...
 

the_king

مدیرکل انجمن
من کلا قضیه ی Mask رو دقیق متوجه نشدم که چرا توی KeyData ، اگه کنترل رو به تنهایی مد نظرمون باشه ، باید هم مقدار کلید و هم مقدار mask اش رو با هم اور کنیم ولی وقتی دکمه ی ترکیبی میشه ، مقدار Mask رو نباید چک و اور کنیم!
ممنون :rose:
همچین چیزی نیست، اینو کی به شما گفته؟ پست من رو که خونده بودید لابد. صریحا میگم این Control ئه Mask شه، بعد باز می گید چرا نباید چک کنیم.

آها وقتی هیچ آرگومانی نمیدیم ، خالی هه
خوب خالی باشه . دیگه مقدار قرار دادن توی یک شی arraylist فکر نکنم ربطی به خالی بودنش داشته باشه؟ اگه به خالی بودنش ربط داره ، الان در همین کد پس چطور با متد arraylist.Add اش میشه پرش کرد؟! وگرنه با متد add اش هم نباید پر شه
سوال تون رو یکجور می پرسید که انگار دارید با arraylist لج می کنید. هر متد و تابع و پروپرتی ای کاربرد خودشو داره، اگه قرار باشه مشابه هم باشند که اضافی ها رو حذف می کنند، Add چه ربطی به مقدار دهی در یک اندیس مشخص مثل arraylist داره؟ Add به انتهای لیست عضو جدید اضافه می کنه، شما هزار بار هم به [arraylist[0 مقدار بدید، طول مجموعه ثابته، اما شما 1000 بار Add رو اجرا کنید، طول لیست به میزان 1000 عضو افزایش پیدا می کنه. شما اول دو تا مورد کاملا مجزا که ربطی بهم ندارند رو یکی فرض می کنید و بعد می گید چرا شرایط شون مثل هم نشد.

جور دیگه ای بهتره بگم . اینکه اولا مثل آرایه ها ، arraylist هم باید تعداد اعضای آرایه هاشون مشخص باشه تا مقدار بهش داد و ارور ArgumentOutOfRange رو نده؟ اگه آره ، پس چرا پروپرتی Capacity رو که مقداردهی میکنیم ، که طبعا باید تعداد اعضاش رو مشخص کنه و در خط بعد با روش ایندکس گذاری ، مقداردهی میکنیم ، باز هم ارور میده؟ یعنی چرا این هم ارور میده؟:
کد:
ArrayList a = new ArrayList(3);
a[0] = "abc";
Capacity و Count با هم فرق می کنند؛ Capacity طول حافظه ای است که در حالت فعلی به اون مجموعه تخصیص داده شده، یعنی حداکثر تعداد اعضاء ای که این حافظه میتونه عضو توش قرار بده، نه تعداد اعضاء فعلی. مادامی که Capacity از Count بزرگتر باشه، برای قرار دادن عضو جدید جا هست و نیازی به تخصیص حافظه بزرگتر نیست، به محض اینکه Capacity کفاف نداد، باید حافظه بزرگتری به مجموعه تخصیص داده بشه و داده های قبلی کپی بشوند در حافظه جدید و حافظه قبلی آزاد بشه و Capacity بیشتر بشه. این یعنی سربار. اینکه مقدار Capacity رو میشه تغییر داد برای اینه که اگه برنامه نویس میدونه که در آینده قراره چند هزار عضو به مجموعه اضافه بشه از همون ابتدا Capacity رو یک مقدار دست بالا تعیین کنه تا هی موقع درج کردن عضو جدید حافظه مجموعه جابجا و بازنویسی نشه. این قضیه ربطی به اینکه اون اندیس در مجموعه موجود نیست نداره.

و دوما وقتی حتی پروپرتی Capacity شو مقداردهی نمیکنیم ، پس چرا با متد add ، مقداردهی میشه و ارور ArgumentOutOfRange رو نمیده ؟ البته اگه مشکل از مشخص نکردن طول arraylist هست وگرنه اگه نیست ، پس چرا با روش ایندکس گذاری که مقداردهی انجام میشه ، ارور میده؟
کلا میشه با روش ایندکس گذاری مقداردهی کرد arraylist رو؟ اگه آره ، یه مثال میزنین؟
Capacity یک مقدار ثابت نیست، قابل افزایشه؛Add ببینه عضو جدید جا نمیشه Capacity رو افزایش میده.
کاری که شما میخواهید بکنید شاید در یکسری مجموعه های خاص معنی بده (اینکه ببینه چون اون اندیس نیست طول آرایه رو افزایش بده) اما در مورد ArrayList وقتی اندیس فلان موجود نیست، نیست دیگه، چطور میخواهید مقدارش رو عوض کنید وقتی خودش نیست.
کاربرد ArrayList برای مواقعی ئه که اولا نوع اشیاء در کل مجموعه یکسان نیست، ثانیا تعداد و اندیس قرار گیری اعضاء متغیر ئه.
حتی اگه یکی از این شرط ها برقرار نباشه ArrayList انتخاب نادرستیه. وقتی شما دارید با اندیس به ArrayList عضو می دهید معنی اش اینه که میدانید محل قرار گیری شون کجا است؛ ArrayList برای اینجور کاربرد ها طراحی نشده. دارید از چیزی استفاده می کنید که برای کاربرد شما نیست. خودتون انتخاب نادرستی کرده اید. تقصیر ArrayList نیست. وقتی میدانید محل قرار گیری اعضاء کجا است بهتره از آرایه استفاده کنید.

ممنون
این سئوال در صفحه ی 8 ، جواب دادین
این ربطی به Brush نداره : اول اینکه چرا کلاس System.Drawing.SystemBrushes رو نمیشه ازش شی ساخت؟ ظاهرا متد سازنده نداره ، پس باید متد سازنده ی پیش فرض داشته باشه و باید بشه ازش شی ساخت
ولی تمام اعضاش public static هستن ولی جای تعجب اینه که بعد از گذاشتن نقطه ، بعد از System.Drawing.SystemBrushes ، هیچ عضوش رو نمیاره !

هدف اصلی اینه که منابع اصلی سیستم مثل Brush ها که محدودیت تعداد دارند الکی صرف نشن. Brush های مرسومی مثل Control و Black و White و Window و ... اونقدر در هر برنامه و مدام استفاده میشن که اگه قرار باشه هر بار برای یک رسم یک نسخه جدیدش ازشون ساخته بشه دیگه فضای Brush رو همین چهار تا پر می کنند. قرار نیست از اینجور Brush ها شیء جدید بسازید، باید بصورت اشتراکی از یکی شون استفاده کنید که خود سیستم بهتون میده و نمیذاره هم نابودش کنید چون اشتراکی ئه. وقتی هم تم ویندوز عوض شد اونها هم مقدارشون عوض میشه و همه برنامه ها تغییر تو رسم شون دیده میشه. اینکه ساختن شیء ازشون پیش بینی نشده برای همینه که اصلا ساختنش که اشتراکی استفاده بشه.

ولی تمام اعضاش public static هستن ولی جای تعجب اینه که بعد از گذاشتن نقطه ، بعد از System.Drawing.SystemBrushes ، هیچ عضوش رو نمیاره !
یا ازش متغیر ساخته اید که چون static اند و ربطی به متغیر تون ندارند نشون شون نمیده یا یک اشتباهی دارید وگرنه SystemBrushes همه اون اعضاء static رو لیست می کنه که از بین شون انتخاب کنید.
ولی سئوال مهم اینه که چرا وقتی شی picturebox میسازیم ، در رویداد paint اش که کد زیر رو مینویسیم ، هیچ شکلی رو توی picturebox نمیکشه؟ ولی برای بقیه ی کنترل ها مثل usercontrol و form ، مشکلی نداره :

کد:
private void picBoxPaint_Paint(object sender, PaintEventArgs e)
        {
            Graphics picBoxGraphics = this.picBoxPaint.CreateGraphics();
            Brush drawBrush = new SolidBrush(Color.Pink);
            picBoxGraphics.DrawString("salam", new Font("Arial", 15), drawBrush, new PointF(30, 10));

        }
چون Paint گرافیک خودشو داره، در داخل Paint نمیان CreateGraphics اجرا کنن، کدتون ایراد داره، دارید وسط یک رویداد رسم کنترل یک گرافیک جدید می سازید :
کد:
        private void picBoxPaint_Paint(object sender, PaintEventArgs e)
        {
            Brush drawBrush = new SolidBrush(Color.Pink);
            e.Graphics.DrawString("salam", new Font("Arial", 15), drawBrush, new PointF(30, 10));
        }
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
SortedList یک Dictionary ئه چون از اینترفیس IDictionary ارث بری می کنه، طبق تعریف IDictionary اون enumerator که شما با foreach ازش استفاده می کنید با نوع DictionaryEntry سازگاره. روی اسم هر کلاسی کلید F12 رو بزنید ساختار اش رو می بینید.

اینو در صفحه ی 9 گفته بودین
استاد علی ، منظورتون اینه که متغییر در حلقه ی foreach (معمولا با نام item) ، به خروجی متد GetEnumerator در شی از کلاسی که بهش داده شد ، نگاه میکنه و اون خروجی رو برمیگردونه؟
اگه این طوری باشه که فکر نکنم باشه ، متد GetEnumerator در کلاس SortedList از نوع IDictionaryEnumerator هه ولی استراکچر DictionaryEntry اصلا فرزند IDictionaryEnumerator هم نیست !
کلاس DictionaryEntry و خروجی متد GetEnumerator ، با هم سنخیتی ندارن ، پس این نوع چجوری از خروجی foreach برای اشیاء های کلاس SortedList از آب درمیاد؟!
 

the_king

مدیرکل انجمن
اینو در صفحه ی 9 گفته بودین
استاد علی ، منظورتون اینه که متغییر در حلقه ی foreach (معمولا با نام item) ، به خروجی متد GetEnumerator در شی از کلاسی که بهش داده شد ، نگاه میکنه و اون خروجی رو برمیگردونه؟

foreach خروجیشو که بر نمی گردونه، ازش استفاده می کنه، قبلا گفتم، foreach خودش مستقیما هیچ کاری با طول مجموعه و اندیس ها و ... نداره، فقط رجوع می کنه به اون کلاس که GetEnumerator بر می گردونه و هر چی اون و با هر ترتیبی بهش بده استفاده می کنه.

اگه این طوری باشه که فکر نکنم باشه ، متد GetEnumerator در کلاس SortedList از نوع IDictionaryEnumerator هه ولی استراکچر DictionaryEntry اصلا فرزند IDictionaryEnumerator هم نیست !
کلاس DictionaryEntry و خروجی متد GetEnumerator ، با هم سنخیتی ندارن ، پس این نوع چجوری از خروجی foreach برای اشیاء های کلاس SortedList از آب درمیاد؟!
آخه ربطی به هم ندارند، IDictionaryEnumerator کارش اینه که پیمایش کنه و عضو تحویل بده، دلیلی نداره که خودش از نوع اعضاء باشه که.
 

the_king

مدیرکل انجمن
foreach که خروجی نداره، foreach یکسری عضو رو یکی یکی میفرسته داخل بلاک خودش. خودشم اصلا درگیر مجموعه نیست، تمام مسئولیت و کارکرد پیمایش به Enumerator ئه بستگی داره. هر موجودیتی هم که Enumerator نداشته باشه foreach رد می کنه چون بدون Enumerator کار نمی کنه. Enumerator هم خودش یک نوع ئه، اعضاء ای که برمی گردونه یک نوع دیگه، اینها قرار نیست با هم تطبیق داشته باشند.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
شما یک متغیر تعریف کردید به نام loc_2 و بهش میگید این مثل پروپرتی ئه که من مثال زدم. شما کجای کدتون this.Location.X = 7 دارید؟ Variable و Property دو تا موجودیت جدا هستند، از نظر شما متغیر همون پروپرتی ئه؟ شما تو کدتون می نویسید this.loc_2.X = 7 و مستقیما مقدار داخل فیلد ها و پروپرتی های متغیر رو تغییر می دهید و از هیچ Property ای هم استفاده نمی کنید، با اصرار کردن که نمیشه چیزی که شبیه مثال دیگه ای نیست یکی فرض کرد.

اول تشکر بی نهایت میکنم ازتون استاد علی بخاطر اینکه وقت تونو برام صرف کردین:rose: نمیخواستم این جور مزاحمتون بشم و پی در پی ازتون سئوال کنم ولی حداقل برای درک کامل تر مخصوصا برای آموزش ها ، نیاز دارم به درک کامل . میدونم خسته شدین ولی اگه منو تا آخر سئوالاتم تحمل کنین ، ممنون میشم . منم که یه چیز رو خیلی دیر یاد میگیرم
فعلا این پست تون رو خوندم و جواب بدم :
متغییر همون پروپرتی نیست ولی کار هم دیگه رو که تقریبا انجام میدن یعنی پروپرتی هم سر آخر مقادیرشو داخل یه متغییر مینویسه و مقادیرشو از اون متغییر میخونه . چه خودمون برای بدنه ی set و get پروپرتی ، بدنه ای بنویسیم و چه پروپرتی اتوماتیک باشه ؛ بالاخره مقادیرشونو توی یک متغییر مینویسن و میخونن
بنابراین به نظرم پروپرتی همون کار یک متغییری که یک متغییر دیگه داخلش قرار میگیره (چه از نوع struct که کپی میشه مقادیرشون و چه از نوع کلاس که اشاره گر به یه مقدار میشن) رو میکنه
مگه این طور نیست؟


هر دو چطور یه کار رو می کنند؟ اگر یک کار رو می کنند پس متغیر چیز بیخودیه و نباید باشه. یکبار یک کاغذ به نام loc رو بر میدارید رو در کادر X اش می نویسید 4. یکبار هم اول از این کاغذ کپی می گیرید و داخل کادر X اون کاغذ کپی می نویسید 2. این دو تا کاغذ یکی هستند؟ شما هر بلایی سر کاغذ کپی بیارید هیچ ربطی به کاغذ اول نداره. this.Location که this.loc نیست، یک کپی از مقدار this.loc ئه. مفهوم کپی که نیاز به توضیح دادن نداره :
کد:
        private Point _loc;

        public Point Loc
        {
            get
            {
                return _loc;
            }
            set
            {
                _loc = value;
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            _loc = new Point(0, 0);
            var a = _loc;
            a.X = 1;
            var b = a;
            b.Y = 2;
            var c = _loc;
            c.X = 3;
            var d = Loc;
            d.Y = 4;
            MessageBox.Show(string.Format("_loc={0} a={1} b={2} c={3} d={4}", _loc, a, b, c, d));
        }
نه
منظورم این نبود که this.Location برابر this.loc هه
منظورم مقایسه ی کد اول یعنی خط this.loc_2.X = 7 و this.Location.X = 2 هه . یعنی مقایسه ی متغییر loc_2 و پروپرتی Location


شی جدید یعنی شیء متفاوت. تفاوت بین ()new Button و ()new Button چیه؟ تفاوت شون اینه که یک شیء واحد نیستند. مقدار فیلد هاشون هم کاملا یکسان باشه خودشون شیء واحدی نیستند.
درسته

اما struct ها Value Type اند، تفاوتی بین ()new Point و ()new Point نیست و نبایدم باشه.
آها منظورتون اینه که توی struct ها وقتی بهشون (فرضا به یک متغییر) شی جدید میدیم ، بجای اینکه حافظه ی جدیدی در رم رو اشغال کنن ، حافظه ی قبلی خودشون رو بازنویسی میکنن؟
بعد اینکه فرضا داخل یه استراکچری ، یه عضوی از نوع کلاس مثل همین button باشه . اون وقت شی ای که به این button میدیم ، شبیه کلاس عمل میکنه؟ یعنی مقدار جدیدی که بهش میدیم ، حافظه ی جدیدی میگیره یا مثل استراکچرهاست؟

متد سازنده ای که شما می خواهید عملا میخواد همچین ساختاری رو بهم بزنه، بگه ()Point برابر ()Point نیست، چون این یک شیء ئه با مقادیری و اون یک شیء دیگری با مقادیر دیگه ای. چنین چیزی برای Value Type ها اصلا معنی نداره، اینها Reference Type نیستند.
این تیکه رو دقیق متوجه نشدم
بی زحمت ، با مثال کد ، مثال بزنین ، درکش برام راحت تره


2 و 4 و 6 و 8 و 10 و 12 همه شون ضریب 2 هستند، 4 | 2 برابر 6 ئه، 2 | 6 برابر 6 ئه (یعنی اصلا 2 | 6 رو نمیشه از 6 تفکیک کرد)، 2 | 8 برابر 10 ئه و ...
نه
ببخشید
منظورم از ضریب 2 ، بصورت باینری بود . مثلا 0 و 1 و 2 و 4 و 8 و 16 و 32 و 64 و 128 و ....
توی این حالت 4|2 هم اور بشن و جواب 6 بشه ، این جوابِ 6 اصلا در هیچ مقدار دیگه ای در بالا وجود نداره
-----------
هر چند با قضیه ی Mask هنوز مشکل دارم ولی کلیت کارش پس اینجوری هه که توی KeyData ، اگه بخوایم فقط یک دکمه رو چک کنیم که فشرده شده هست یا نه ، هم باید مقدار Mask شو و هم مقدار غیر Mask اش رو چک کنیم . درسته؟ یا این قضیه فقط برای کلیدهای کنترلی مثل سیفت و این چیزاست؟ و اگه هم بخوایم کلیدهای ترکیبی رو چک کنیم ، فقط دیگه لازم نیست مقدار Mask اش رو چک کنیم؟
درسته؟
 

the_king

مدیرکل انجمن
اول تشکر بی نهایت میکنم ازتون استاد علی بخاطر اینکه وقت تونو برام صرف کردین:rose: نمیخواستم این جور مزاحمتون بشم و پی در پی ازتون سئوال کنم ولی حداقل برای درک کامل تر مخصوصا برای آموزش ها ، نیاز دارم به درک کامل . میدونم خسته شدین ولی اگه منو تا آخر سئوالاتم تحمل کنین ، ممنون میشم . منم که یه چیز رو خیلی دیر یاد میگیرم
فعلا این پست تون رو خوندم و جواب بدم :
متغییر همون پروپرتی نیست ولی کار هم دیگه رو که تقریبا انجام میدن یعنی پروپرتی هم سر آخر مقادیرشو داخل یه متغییر مینویسه و مقادیرشو از اون متغییر میخونه . چه خودمون برای بدنه ی set و get پروپرتی ، بدنه ای بنویسیم و چه پروپرتی اتوماتیک باشه ؛ بالاخره مقادیرشونو توی یک متغییر مینویسن و میخونن

بنابراین به نظرم پروپرتی همون کار یک متغییری که یک متغییر دیگه داخلش قرار میگیره (چه از نوع struct که کپی میشه مقادیرشون و چه از نوع کلاس که اشاره گر به یه مقدار میشن) رو میکنه
مگه این طور نیست؟
نه، نیست. Property یک واسطه است، برای ارجاع با Reference مشکلی پیش نمیاد ولی باز به این معنی نیست که همون کار رو می کنه. در مورد مقدار Value Type هم که کلا در struct می بینید، شما وقتی مقدارش رو از یک متغیر return می کنید دیگه مقداری که برگردونده میشه کاری با اون متغیر و مقدارش نداره، کاملا یک کپی مستقل ئه.

آها منظورتون اینه که توی struct ها وقتی بهشون (فرضا به یک متغییر) شی جدید میدیم ، بجای اینکه حافظه ی جدیدی در رم رو اشغال کنن ، حافظه ی قبلی خودشون رو بازنویسی میکنن؟

در مورد Overwrite و بازنویسی حافظه اشیاء قبلا بارها صحبت کردیم، بار ها گفتم که این مربوط به GC ئه و قرار نیست حافظه قبلی بازنویسی بشه. باز میگید بازنویسی حافظه قبلی. اینکه چرا حاضر نیستید ازش دست بکشید رو نمی دونم.
بعد اینکه فرضا داخل یه استراکچری ، یه عضوی از نوع کلاس مثل همین button باشه . اون وقت شی ای که به این button میدیم ، شبیه کلاس عمل میکنه؟ یعنی مقدار جدیدی که بهش میدیم ، حافظه ی جدیدی میگیره یا مثل استراکچرهاست؟
کلاس که کلاس می مونه، ارجاع کپی میشه، اون شیء button و حافظه اش متعلق به struct نیست، در struct فقط ارجاع بهش قرار داره، از کل حافظه اون شی button فقط اندازه یک اشاره گر به struct تعلق داره، حافظه button مستقل ئه. و در struct فقط یک اشاره گر ئه. اون اشاره گر به سادکی کپی میشه. خود شیء button یک نسخه بیشتر نیست و در هر دو مقدار struct به یک button واحد اشاره می کنند.


این تیکه رو دقیق متوجه نشدم
بی زحمت ، با مثال کد ، مثال بزنین ، درکش برام راحت تره
مثال زدم دیگه، چیو مثال بزنم؟ فرض کنیم سه تا کلید داریم، با مقادیر 2 و 4 و 6 که هر سه هم مضرب 2 هستند. 2 | 4 میشه 6 . اینو روی کاغذ و با ماشین حساب و کد #C هم می توانید حساب کنید. حالا وقتی مقدار 6 رو بهتون بدن چطوری میخواهید بگید این 6 ترکیبی از دو کلید 2 و 4 ئه که OR شون شده 6 یا فقط کلید سوم به تنهایی ئه؟ هیج راهی وجود نداره چون تمامی بیت های 1 ئه اون کلید های اول و دوم در سومی 1 ئه.
2 | 6 برابر 6 ئه و 4 | 6 هم برابر 6 ئه، بیت های این دو کلید اول و دوم بصورت کامل توی مقدار کلید سوم هضم میشن و چیزی ازشون نمیمونه که تفاوت ایجاد کنه.

نه
ببخشید
منظورم از ضریب 2 ، بصورت باینری بود . مثلا 0 و 1 و 2 و 4 و 8 و 16 و 32 و 64 و 128 و ....
توی این حالت 4|2 هم اور بشن و جواب 6 بشه ، این جوابِ 6 اصلا در هیچ مقدار دیگه ای در بالا وجود نداره
چه باینری و چه دسیمال و چه هگزادسیمال 2 دو ئه و ضریب 2 هم همون ضریب 2 ئه، اون چیزی که شما میگید توان 2 ئه. شما دارید روی Keys حرف می زنید یا دارید راه حل جدید ارائه می کنید؟ وقتی عدد مقدارش 32 بیتی ئه 32 تا بیت بیشتر ندارید و چون صفحه کلید خیلی بیشتر از 32 کلید داره نمیشه به هر کدوم یک بیت منحصر بفرد اختصاص داد. اینکه دیگه جای بحث نداره. Keys هم به همین دلیل به شیوه دلخواه شما با توان های 2 مقدار دهی نشده، نزدیک 200 تا کلید اون تو ئه، شما Keys رو مقدار 200 بیتی فرض می کنین که بگید هر مقدارش توانی از 2 باشه؟ عکس مقادیر داخلش رو هم که نشون تون دادم.
هر چند با قضیه ی Mask هنوز مشکل دارم ولی کلیت کارش پس اینجوری هه که توی KeyData ، اگه بخوایم فقط یک دکمه رو چک کنیم که فشرده شده هست یا نه ، هم باید مقدار Mask شو و هم مقدار غیر Mask اش رو چک کنیم . درسته؟ یا این قضیه فقط برای کلیدهای کنترلی مثل سیفت و این چیزاست؟ و اگه هم بخوایم کلیدهای ترکیبی رو چک کنیم ، فقط دیگه لازم نیست مقدار Mask اش رو چک کنیم؟
درسته؟
خیر درست نیست، اگر اون کلید در همون لحظه فشرده نشده و از قبل فشرده بوده که لابد کلید کنترلی ئه و دیگه خود کلید کنترلی در مقدار KeyData نیست که بخواهید چک کنید، فقط Mask اش موجوده.
اگر هم کلید کنترلی نیست، مثلا A کلید کنترلی نیست، که فقط مقدار خودش رو داره، Mask نداره که، برای نمیدونم چندمین بار میگم، فقط چند تا کلید خاص کنترلی هستند که Mask دارند که اونم مقادیرشون توانی از 2 ئه و انتهای Keys مقدار دهی شدن. هر کلیدی که کنترلی باشه در چک کردنش داخل KeyData باید مقدار Mask اش باشه، حالا چه تنها فشرده شده باشه و چه همراه کلید دیگه ای. من هیچ حالتی به عنوان لازم نیست نگفتم تا حالا. این لازم نیست رو خودتون اختراع کردین :D
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
همچین چیزی نیست، اینو کی به شما گفته؟ پست من رو که خونده بودید لابد. صریحا میگم این Control ئه Mask شه، بعد باز می گید چرا نباید چک کنیم.
ممنون استاد علی
ببخشید . اشتباه گفتم
اولا که اون مقدارهایی که آخرشون Key ندارن مثل Control رو Mask میگن و اونایی که دارن مثل ControlKey رو مقدار کلیدی میگن
دوما که برعکس گفتم و درستش میشه :
توی KeyData ، اگه کنترل رو به تنهایی مد نظرمون باشه ، باید هم مقدار کلید و هم مقدار mask اش رو با هم اور کنیم ولی وقتی دکمه ی ترکیبی میشه ، مقدار کلیدی رو نباید چک و اور کنیم! (فقط باید از mask و اون دکمه مثل A و کلا دکمه ی مورد نظرمون استفاده و اور کنیم)
این درسته ؟


سوال تون رو یکجور می پرسید که انگار دارید با arraylist لج می کنید. هر متد و تابع و پروپرتی ای کاربرد خودشو داره، اگه قرار باشه مشابه هم باشند که اضافی ها رو حذف می کنند، Add چه ربطی به مقدار دهی در یک اندیس مشخص مثل arraylist داره؟ Add به انتهای لیست عضو جدید اضافه می کنه، شما هزار بار هم به [arraylist[0 مقدار بدید، طول مجموعه ثابته، اما شما 1000 بار Add رو اجرا کنید، طول لیست به میزان 1000 عضو افزایش پیدا می کنه. شما اول دو تا مورد کاملا مجزا که ربطی بهم ندارند رو یکی فرض می کنید و بعد می گید چرا شرایط شون مثل هم نشد.


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


Capacity یک مقدار ثابت نیست، قابل افزایشه؛Add ببینه عضو جدید جا نمیشه Capacity رو افزایش میده.
کاری که شما میخواهید بکنید شاید در یکسری مجموعه های خاص معنی بده (اینکه ببینه چون اون اندیس نیست طول آرایه رو افزایش بده) اما در مورد ArrayList وقتی اندیس فلان موجود نیست، نیست دیگه، چطور میخواهید مقدارش رو عوض کنید وقتی خودش نیست.
کاربرد ArrayList برای مواقعی ئه که اولا نوع اشیاء در کل مجموعه یکسان نیست، ثانیا تعداد و اندیس قرار گیری اعضاء متغیر ئه.
حتی اگه یکی از این شرط ها برقرار نباشه ArrayList انتخاب نادرستیه. وقتی شما دارید با اندیس به ArrayList عضو می دهید معنی اش اینه که میدانید محل قرار گیری شون کجا است؛ ArrayList برای اینجور کاربرد ها طراحی نشده. دارید از چیزی استفاده می کنید که برای کاربرد شما نیست. خودتون انتخاب نادرستی کرده اید. تقصیر ArrayList نیست. وقتی میدانید محل قرار گیری اعضاء کجا است بهتره از آرایه استفاده کنید.

لج چیه؟:)
اولا که کاربردشو میدونم . یعنی میدونم اگه مقدار آرایه ای مشخص باشه ، بهتره بجای لیست ها و arraylist ها از آرایه استفاده کنیم و دوما که اگه انواع مختلف داده ای نداشتیم ، بهتره از list ها بجای arraylist ها استفاده کنیم .
فقط برای اطلاعات بیشتر میخوام بدونم
ممنون بابت توضیح کامل متد add و اندیس و count و capacity
اما منظورمو فکر کنم کامل متوجه نشدین
ببینین مثلا یه
arraylist با ظرفیت 5 عضو داریم بنابراین باید بتونیم با مشخص کردن اندیس ایندکسرش ، 5 تا عضو بهش بدیم دیگه؟ درسته؟ چون براش 5 تا خونه ی خالی در نظر گرفتیم . پس چرا نمیشه این کار رو کرد؟ یعنی کد زیر چرا ارور ArgumentOutOfRangeException رو میده؟ :
کد:
            ArrayList arr = new ArrayList(5);
            arr[0] = 3;

هدف اصلی اینه که منابع اصلی سیستم مثل Brush ها که محدودیت تعداد دارند الکی صرف نشن. Brush های مرسومی مثل Control و Black و White و Window و ... اونقدر در هر برنامه و مدام استفاده میشن که اگه قرار باشه هر بار برای یک رسم یک نسخه جدیدش ازشون ساخته بشه دیگه فضای Brush رو همین چهار تا پر می کنند. قرار نیست از اینجور Brush ها شیء جدید بسازید، باید بصورت اشتراکی از یکی شون استفاده کنید که خود سیستم بهتون میده و نمیذاره هم نابودش کنید چون اشتراکی ئه. وقتی هم تم ویندوز عوض شد اونها هم مقدارشون عوض میشه و همه برنامه ها تغییر تو رسم شون دیده میشه. اینکه ساختن شیء ازشون پیش بینی نشده برای همینه که اصلا ساختنش که اشتراکی استفاده بشه.


یا ازش متغیر ساخته اید که چون static اند و ربطی به متغیر تون ندارند نشون شون نمیده یا یک اشتباهی دارید وگرنه SystemBrushes همه اون اعضاء static رو لیست می کنه که از بین شون انتخاب کنید.
ممنون
بله
اشتباه از من بود
چندین حالت مختلف رو داشتم تست میکردم ، کلمه ی کلیدی new قبل اش گذاشتم ، واسه همین مشکل پیش اومد


چون Paint گرافیک خودشو داره، در داخل Paint نمیان CreateGraphics اجرا کنن، کدتون ایراد داره، دارید وسط یک رویداد رسم کنترل یک گرافیک جدید می سازید :
کد:
        private void picBoxPaint_Paint(object sender, PaintEventArgs e)
        {
            Brush drawBrush = new SolidBrush(Color.Pink);
            e.Graphics.DrawString("salam", new Font("Arial", 15), drawBrush, new PointF(30, 10));
        }
ممنون
گرافیک رو از همون شی موجود بگیریم هم شی جدیدی ایجاد میکنه؟
پس باید شی گرافیک رو از متغییر رویدادی بگیریم دیگه؟
اما چرا پس توی رویداد paint برای کنترل form1 و usercontrol ها اون کدم مشکلی نداشت (مثلا برام فرم ، با همین this.CreateGraphics() شی گرافیک میگرفتم) ؟
 

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

بالا