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

شروع موضوع توسط saalek110 ‏27 دسامبر 2006 در انجمن برنامه‌نویسی C و هم خانواده‌هایش

  1. SajjadKhati

    SajjadKhati کاربر فعال <A href="http://forum.majidonline.com/f

    ارسال‌ها:
    630
    تشکر شده:
    152
    امتیاز دستاورد:
    43
    ممنون ولی من قضیه ی برگردوندن یک کلاس رو متوجه نشدم . نه اینکه ندونم برگردوندن کلاس یعنی چه . میدونم ولی خوب که چی؟
    مثلا ما وقتی مقدار عدد رو برمیگردونیم ، بعدا ازش استفاده و فراخونی میکنیم ولی وقتی کلاسی برگردونده میشه مثل کد بالا ، دوباره به خودش اشاره میکنه و فرقی نداره با فراخونی و یا ایجاد شی معمولی از کلاس
    ---------------------
    بعد اینکه من اگه نوع یک داده (متغییر یا آرایه یا نوع بازگشتی یک تابع و ...) رو بخوام بگیرم ، از چه متد یا پروپرتی ای باید استفاده کنم؟ مثلا میخوام یه آرایه یا عضوی از یک آرایه رو بدم و نوع بازگشتی اون رو برگردونه؟
    این رو فهمیدم . هر شی و داده ای ، متد اکستنشن GetType() داره که از نوع داده ای type یا همون کلاس
    type هست که نوع داده ای یا کلاس نوع داده ای شی مورد نظر را برمیگردونه
    --------------------
    یک سئوال دیگه اینکه توی راهنمای intelicence ما از کجا بفهمیم یک چیز رو ، به شی اش اشاره میکنه یا یه کلاس اش؟ یعنی ما باید شی ایجاد شده از اون کلاس رو که توی راهنماش گفت بنویسیم و بعد نقطه بزاریم یا کلاس شو باید بنویسیم و بعد نقطه بزاریم؟
    ---------------------


    من آخر متوجه نشدم چرا موقع استفاده از location باید کلاس point رو new کنیم؟ چرا بقیه رو new نمیکنیم؟
    چرا مثلا مثل بقیه برای مقداردهی X نباید این طور نوشت؟ و چرا مشکل داره؟ :

    کد (Text):

    button1.Location.X = 100;
     
     
    آخرین ویرایش: ‏9 می 2016
    نوشته شده توسط SajjadKhati در ‏8 می 2016
  2. the_king

    the_king مدیرکل انجمن

    ارسال‌ها:
    10,201
    تشکر شده:
    10,110
    امتیاز دستاورد:
    113
    کلاس بر گردونده نمیشه، یک شیء از نوع کلاس بر گردونده میشه، کلاس مقداری نیست که بشه برگردوند، شما در زبان #C چیزی مثل return Class1 یا return string نمی بینید.
    ایجاد کردن شیء که کلا یک قضیه دیگه است، هر شیء ای مستقل از شیء دیگه است، دو شیء که هر دو شون از یک کلاس اند همچنان دو شیء مجزا اند، یک شیء نیستند.
    کلاس string رو در نظر بگیرید، ()ToString داره، چی بر میگردونه؟ مقدار خودشو. چرا باید همچین متد بیخودی داشته باشه که خودشو بر می گردونه؟
    اینکه یک مشخصه ای خود شیء رو برگردونه الزاما بی منطق و بی فایده نیست. به مدلی که طراح کد برای کلاس اش در نظر گرفته بستگی داره.
    مثلا چون string و در حقیقت System.String یک object ئه و از کلاس System.Object ارث بری می کنه، به اون جهت الزاما ()ToString داره.
     
    نوشته شده توسط the_king در ‏9 می 2016
    SajjadKhati از این پست تشکر کرده است.
  3. SajjadKhati

    SajjadKhati کاربر فعال <A href="http://forum.majidonline.com/f

    ارسال‌ها:
    630
    تشکر شده:
    152
    امتیاز دستاورد:
    43
    ممنون
    جواب قسمت آخر پست بالا رو هم میدادین ممنون میشدم
    و اینکه اگه شی ای بنام button1 داشته باشیم ، چرا کد زیر جواب نمیده؟ :

    کد (Text):

    y = button1.Location;
               
                y.X = 200;
     

    الان این y شی ای از کلاس point نیست؟ یعنی شی ازش برگردونده نمیشه؟ اگه شی برگردونده نمیشه ، پس y کلاس point میشه و باید از این y که همون کلاس pont هست ، شی ایجاد کرد؟
    یه کم قاتی کردم
    :)
     
    نوشته شده توسط SajjadKhati در ‏9 می 2016
  4. SajjadKhati

    SajjadKhati کاربر فعال <A href="http://forum.majidonline.com/f

    ارسال‌ها:
    630
    تشکر شده:
    152
    امتیاز دستاورد:
    43
    سلام
    میخوایم وقتی یه دیالوگی رو که باز شد (مثلا دیالوگ رنگ) و کاربر دکمه ی کنسل رو که زد ، هیچ کاری انجام نده ، باید چی کار کنیم؟
    در کد زیر ، x نباید مقداری رو برگردونه که برابر کنسل باشه (یعنی عضو cancel داشته باشه) تا برنامه نویس متوجه بشه که کاربر دکمه ی کنسل رو زد یا نه؟ :

    کد (Text):

    DialogResult x = colorDialog1.ShowDialog();
                if (x.)
     
    پس چرا نداره و باید از کجا بفهمیم؟

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

    من قبلا یادم میومد این کد زیر رو که بصورت این جوری مینوشتم :



    کد (Text):

    DialogResult x = MessageBox.Show("","");
                if (x.)
     


    بعدش عضوهای x که همون دکمه های YES و NO و CANCEL و ... باشه میومد و میتونستیم انتخاب کنیم ولی الان نمیدونم کجاش اشکال داره که نمیاد !!
     
    آخرین ویرایش: ‏10 می 2016
    نوشته شده توسط SajjadKhati در ‏10 می 2016
  5. the_king

    the_king مدیرکل انجمن

    ارسال‌ها:
    10,201
    تشکر شده:
    10,110
    امتیاز دستاورد:
    113
    تنظیمات صفحه کلید توی ویژوال استدیو با توجه به زبان برنامه نویسی پیشفرض و یا Customize کردن خودتون قابل تغییر ئه، اما اصولا با کلید F12 می توانید از Go to Definition استفاده کنید که تعریف هر موردی که
    چشمکزن کد روی اون قرار داره رو میاره. حتی مواردی که کدش رو شما ننوشته باشید. اونجا با توجه به کد پروتوتایپ مشخصه، اگه عبارت static باشه مربوط به کلاس ئه و اگر static نباشه مربوط به شیء ئه.

    یک لحظه فکر کنید که Location و Point رو نمی شناسید و خودتان می خواهید یک کد Property بنویسید که مختصات یک نقطه رو بخونه و یا بنویسه.
    اول باید نقطه رو تعریف کنید، دو تا گزینه دارید، نقطه رو یا با کلاس تعریف می کنید و یا با ساختار.
    کد (Text):

        class PointClass
        {
            public int X;
            public int Y;
        }
     
    کد (Text):

        public struct PointStruct
        {
            public int X;
            public int Y;
        }
     
    مساله سر فرق اساسی ایندو تا است، کلاس همیشه با ارجاع کار می کنه و ساختار همیشه با مقدار.
    کد (Text):

                var p1 = new PointStruct();
                p1.X = 4;
                var p2 = p1;
                p2.X = 12;
     
    مقدار p1.X همان 4 ای که در سطر دوم می نویسید می ماند و 12 نمی شود، چون var p2 = p1 یک کپی جدید از مقدار p1 را در p2 می نویسد، به همان شیء p1 ارجاع نمی دهد، مستقل از p1 است.

    کد (Text):

                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 رو بنویسید،
    کد (Text):

            public PointClass Location
            {
                get;
                set;
            }
     
    کد (Text):

            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

    اگر اون فرم دست سازه و شما کدش رو شما می سازید یادتون نره که برای دکمه Cancel کد نویسید :
    کد (Text):

    [COLOR="#D3D3D3"]        private void button1_Click(object sender, EventArgs e)
            {[/COLOR]
                DialogResult = DialogResult.Cancel;
                Close();
    [COLOR="#D3D3D3"]        }[/COLOR]
     
    کد (Text):

                DialogResult x = colorDialog1.ShowDialog();
                if (x == DialogResult.OK)
                {
                    //Your Code
                }
     
    کد (Text):

                if (colorDialog1.ShowDialog() == DialogResult.OK)
                {
                    //Your Code
                }
     
    کد (Text):

                var x = colorDialog1.ShowDialog();
                if (x == DialogResult.OK)
                {
                    //Your Code
                }
     
     
    نوشته شده توسط the_king در ‏10 می 2016
    SajjadKhati از این پست تشکر کرده است.
  6. SajjadKhati

    SajjadKhati کاربر فعال <A href="http://forum.majidonline.com/f

    ارسال‌ها:
    630
    تشکر شده:
    152
    امتیاز دستاورد:
    43
    واقعا ممنون آقا علی
    در حال خوندن متن شما بودم که گفتم اینو تست کنم که اولین تجربه ام بود و خیلی چیزا رو بیشتر درک کردم
    این کد رو نوشتم در کلیک یه دکمه :

    کد (Text):

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;




    namespace Project_1
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }


            private void button1_Click(object sender, EventArgs e)
            {
                UnderForm MyFrmObj = new UnderForm();
                MessageBox.Show( MyFrmObj.MyMethodUnderForm().MyMethod("My Text") );
            }
        }




        class UnderForm
        {
            public MyClass MyMethodUnderForm()
            {
                MyClass objUnderForm = new MyClass();
                return objUnderForm;
            }
        }
    }
     
    بعد یه کلاس دیگه هم نوشتم :

    کد (Text):


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;


    namespace Project_1
    {
        class MyClass
        {
            public string MyMethod(string x)
            {
                return x + " writ by user";
            }
        }
    }
     
    اولا اولین بارم بود که از یه چیزی (متدی) ، یه کلاس رو برگردوندم
    بعد اینکه متوجه شدم فقط شی ای از یک کلاس میتونه برگردونده بشه یعنی خود کلاس نمیتونه برگردونده بشه از یک جایی (متدی پروپرتی ای و ...) . اگه کلاس و اعضاش static باشه هم از جایی نمیشه برگردونده بشه (فقط کلاس های معمولی برگردونده میشن) یعنی در متد MyMethodUnderForm نمیتونیم بنویسیم :

    کد (Text):

    public MyClass MyMethodUnderForm()
            {
                return MyClass;
            }
     
    اما اولین کلاس فراخونی شده میتونه static باشه یعنی بجای کد اول میشه نوشت :

    کد (Text):

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;




    namespace Project_1
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }


            private void button1_Click(object sender, EventArgs e)
            {
                UnderForm MyFrmObj = new UnderForm();
                MessageBox.Show(UnderForm.MyMethodUnderForm().MyMethod("My Text"));


            }
        }




        class UnderForm
        {
            public static MyClass MyMethodUnderForm()
            {
                MyClass objUnderForm = new MyClass();
                return objUnderForm;
            }
        }
    }
     

    ولی خود اون متد یا پروپرتی مون که میخواد کلاس رو برگردونه ، باید شی ای کلاس رو برگردونه نه خود کلاس رو
    هر چند قبلا بصورت نیمه عملی و حتی بصورت تئوری میدونستم همه چی در سی شارپ شی گرا هست اما انگار الان بیشتر درک کردم . مثل همین کد :

    کد (Text):

    MessageBox.Show( MyFrmObj.MyMethodUnderForm().MyMethod("My Text") );
     
    در کد بالا وقتی موس رو روی MyFrmObj میبریم ، میگه MyFrmObj شی ای از کلاس UnderForm هست . بعد که روی MyMethodUnderForm میبریم مینویسه UnderForm.MyMethodUnderForm() که اولا منظورش اینه که یک شی ای کلاس UnderForm باید نوشته باشه قبل اش و بعد نقطه بزارین که به اعضای این کلاس توسط این شی دسترسی داشته باشین و دوما نوع بازگشتی اش کلاس MyClass هست و وقتی میبریم روی MyMethod میگه MyClass.MyMethod() که یعنی چون MyClass سبز رنگ هست یعنی کلاس هست که برای فراخونی اش باید شی ای از این کلاس رو نام ببریم (یا کلا یه چیزی (مثلا متدی و ...) شی ای از این کلاس رو برگردونه) و بعد از اون نقطه میزاریم و به اعضاش دسترسی پیدا میکنیم

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

    مهم :

    نکته ی مهم ای که فهمیدم اینه که جز در اولین کلاس که اونم بصورت static باشه، در بقیه ی موارد هر وقت در راهنمای intelecent ، موقع فراخونی ، کلمه ی سبز رنگ دیدیم ، اون یعنی شی ای از اون کلاس رو بجاش باید بزاریم و مشخص هست بعدش که نقطه بزاریم ، به اعضای اون کلاس دسترسی پیدا میکنیم
    سی شارپ که شی گراست الان بیشتر متوجه میشم که مثلا وقتی مینویسیم :

    کد (Text):

    int x = 5;
     
    در واقع x همون شی ای از کلاس Int32 مون هست و هیچ فرقی نداره که بنویسیم :

    کد (Text):

    Int32 x = new Int32();
     
    یا مثلا وقتی رشته تعریف میکنیم یا آرایه تعریف میکنیم ، در واقع شی از کلاس اون رشته (String و ...) درست میکنیم
    وقتی هم متدی میسازیم که مثلا عدد رو برگردونه ، در واقع مثل همین باعث میشه وقتی اون تابع اجرا میشه ، یک شی از کلاس عدد مورد نظر (Int32 و ...) بسازه بعد که حالا فراخونی این تابع باعث ایجاد شی از کلاس عدد مون شد ، حالا نقطه که میزاریم یعنی در واقع به اعضای اون کلاس عدد مورد نظر (مثلا اعضای کلاس Int32 که همون کلمه ی کلیدی int بود) دسترسی پیدا کنیم که حالا اعضای این کلاس (بسته به ارث بری این کلاس از کلاس های دیگه و اعضای مستقیم خود این کلاس) ، اعضای ToString() و CompairTo() و هر متد و پروپرتی دیگه میتونه باشه و وقتی این عدد را عضو ToString() اش رو انتخاب میکنیم ، چون این متد ، رشته رو برمیگردونه ، در واقع شی ای از کلاس String برامون ایجاد میشه که حالا یه نقطه ی دیگه میزنیم ، به اعضای اون کلاس String دسترسی پیدا میکنیم .
    بنابراین طبق این گفته و کد بالا ، هر متد و پروپرتی و استراکچر و ... ، یا بصورت مستقیم یک شی ای از کلاس رو برمیگردونن یا عدد و رشته و آرایه و این چیزهای رایج در برنامه نویسی رو برمیگردونن که باز خودشون در واقع همون شی از کلاس مورد نظرشون (شی از کلاس رشته و عدد و ... ی مورد نظر) هستند
    و نکته ی مهم اینجاست که دسترسی به اعضای یک کلاس (بعد از نوشتن نقطه) ، به نوع شی کلاس قبلی (قبل از نقطه که نوشتیم) بستگی داره
    پس در واقع ، در سی شارپ ، همه ی انواع بازگشتی ، شی ای از یک کلاس هستند و همونطوری که میخوایم تابع را فراخونی کنیم ، علامت پرانتز (برای دادن آرگومان) را باید بنویسیم و یا اگه به اعضای آرایه مون میخوایم دسترسی داشته باشیم ، باید با کلوشه و دادن اندیس این کار رو کنیم ، برای فراخونی یا برگردوندن یک کلاس هم بجز اون حالت خواصی که گفته شد ، باید و باید از اون کلاس شی بسازیم و نمیشه همینجوری موقع برگردوندن یک کلاس ، کلاس رو بدون ایجاد شی ای ازش برگردوند
    ولی موقع تعریف متدی که نوع بازگشتی اش کلاس هست ، در هدر اون متد ، نوع بازگشتی که همون کلاس(نام کلاس) هست رو باید بنویسیم و نباید شی ای از کلاس رو در هدر این تابع بنویسیم . در واقع کل کلاس (نام کلاس) ، نوع بازگشتی هست . مثلا وقتی که مینویسیم :

    کد (Text):

    int z()
            {
                int x = 5;
                return x;
            }

     
    در واقع int که کلاس Int32 هست یعنی نام کلاس هست ، دقیقا همون نوع بازگشتی مون هست و x که شی ای از کلاس Int32 هست ، مقدار اون کلاس مورد نظر هست بنابراین در کد بالا که همین هست :

    کد (Text):

    class UnderForm
        {
            public MyClass MyMethodUnderForm()
            {
                MyClass objUnderForm = new MyClass();
                return objUnderForm;
            }
        }
     
    مقدار بازگشتی تابع MyMethodUnderForm مون که نام کلاس گذاشتیم ، در واقع همین نام کلاس MyClass ، نوع بازگشتی مون هست و شی objUnderForm که شی ای از این کلاس هست ، مقدار این نوع از کلاس MyClass مون هست
    پس نکته ی بسیار مهم اینه که کلاس ها همون نوع بازگشتی و شی از اون کلاس همون مقدار بازگشتی اون کلاس هستند

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

    البته اینو نوشتم که مبتدیانی مثل من بیشتر متوجه شن و خودمم در آینده اگه فراموش کردم دوباره نگاه بندازم . البته اگه اشتباه ننوشته باشم :)
    ممنون ازتون آقا علی
    حالا برم ادامه ی کدهای شما رو بخونم :rose:
    :)
     
    نوشته شده توسط SajjadKhati در ‏10 می 2016
  7. SajjadKhati

    SajjadKhati کاربر فعال <A href="http://forum.majidonline.com/f

    ارسال‌ها:
    630
    تشکر شده:
    152
    امتیاز دستاورد:
    43

    ممنون آقا علی :rose:
    تا اینجا رو بلد بودم تقریبا



    اما اینجا رو زیاد متوجه نشدم
    بزارین اصولی از روی راهنمای intelecent خود ویژال استودیو بریم . یعنی واقعا به عنوان کسی که چیزی بلد نیستم و میخوام از این راهنما استفاده کنم .
    وقتی مینویسیم button1.Location.X; و وقتی موس رو روی X میبریم ، در راهنما میگه Point.X که طبق چیزهایی که من از پست های بالا میدونم و طبق روال عادی همه ی کدها ، اینه که یک شی ای از کلاس Point بسازیم . نقطه بزاریم و به عضو (پروپرتی) X از این کلاس دسترسی پیدا کنیم پس مینویسیم :

    کد (Text):

    Point MyPnt = new Point(50,200);
     
    بعد چون این پروپرتی X رو که عدد میخواد و همینطور میخوایم set کنیم مینویسیم :

    کد (Text):

    Point MyPnt = new Point(50,200);
    MyPnt.X = 5;
     
    تا اینجا درست هست دیگه طبق راهنمای ویژال استودیو؟ درسته؟
    خوب حالا من میخوام این کد رو روی شی button1 ام اعمال کنم ؛ چی کار باید کنم؟
    اگه میشه طبق این منطق پیش بریم . یعنی مثل کد قبل پرنت و ... نکنیم چون در راهنماش حرفی از پرنت و اینا نزد (میخوام جوری برم که در کدهایی این چنینی فقط راهنمای ویژال استودیو برام کافی باشه یعنی فقط به چیزهایی که اشاره کرد توجه کنیم)
    کلا یه کم این کد پیچیده هست !!
     
    نوشته شده توسط SajjadKhati در ‏10 می 2016
  8. the_king

    the_king مدیرکل انجمن

    ارسال‌ها:
    10,201
    تشکر شده:
    10,110
    امتیاز دستاورد:
    113
    شما یک نقطه تعریف کرده اید به نام MyPnt و هر تغییر مقداری که خواسته اید روی آن می دهید. در انتها اون رو به button1.Location تحویل می دهید تا یک کپی از مقدارش روی button1.Location اعمال شود :
    کد (Text):

                Point MyPnt = new Point(50, 200);
                MyPnt.X = 5;
                button1.Location = MyPnt;
     
    توصیه می کنم که نام متغیر های محلی رو با حروف بزرگ شروع نکنید، یکی از قواعد اصولی کد نویسی ئه که به خوانایی کد کمک می کنه،
    که اسم متغیر های محلی رو با حروف کوچک شروع کنید و اسم متد ها و مشخصه ها رو با حروف بزرگ شروع کنید.
     
    نوشته شده توسط the_king در ‏10 می 2016
    SajjadKhati از این پست تشکر کرده است.
  9. SajjadKhati

    SajjadKhati کاربر فعال <A href="http://forum.majidonline.com/f

    ارسال‌ها:
    630
    تشکر شده:
    152
    امتیاز دستاورد:
    43


    آها
    واقعا ممنون . متوجه شدم . :rose:
    تحلیل اش اینه که همونطور که در مثال زیر :

    کد (Text):

    class NewClass
        {
            int X;
            public int MyMethodUnderForm
            {
                set
                {
                    X = value;
                }
            }
        }
     
    که موقع فراخونی اش مینویسیم :

    کد (Text):

    int x = 10;
                NewClass SecObj = new NewClass();
                SecObj.MyMethodUnderForm = x;
     
    یعنی موقع فراخونی اش ، همون نوع بازگشتی که همون کلاس Int32 باشه ، مقدارش رو که شی ای از همون کلاس هست (شی ای از کلاس Int32 یا متغییر یا همون شی x) میدیم (در سمت چپ مساوی ست میکنیم) ، در این مثال هم از نوع داده ای یا کلاس Point ، یک شی ای از همین کلاس Point رو برای پروپرتی Location که شی ای از این کلاس رو ست یا get میکنه رو حالا در اینجا set میکنیم یعنی همین کدی که دادین :

    کد (Text):

    Point MyPnt = new Point(50, 200);
    button1.Location = MyPnt;
     
    عادت کردم اسما رو کلا با حروف بزرگ شروع کنم آخه با اتوپلی که کار میکردم و میکنم ، از کدهای اتوپلی تقلید کردم :green: . هر چند تنوع تعریف اشیاء و متغییرها توی سی شارپ خیلی هست و بنابراین گفته ی شما درسته ولی تا حالا این نکته رو نمیدونستم . از این به بعد سعی میکنم این طوری که گفتین بنویسم که البته به یادموندن و عادت کردنم طول میکشه .
    بازم ممنون
    :rose:
     
    نوشته شده توسط SajjadKhati در ‏10 می 2016
  10. SajjadKhati

    SajjadKhati کاربر فعال <A href="http://forum.majidonline.com/f

    ارسال‌ها:
    630
    تشکر شده:
    152
    امتیاز دستاورد:
    43
    سلام
    آقا علی من یه کد دیدم که ساختارش این جوری بود که فضای نام using System.IO; داشت و در رویدادی این کد رو :

    کد (Text):

    using (StreamWriter myRead = File.CreateText("C:\\m.txt")) ;
     
    کدش مشکلی نداره ولی اون using قبل اش یعنی چی؟ مگه کلاس ها هم using میشن؟ یعنی بجز فضای نام ، چیزی using میشه؟ حالا اگه using بشه یک کااس ، چی میشه؟ کلا شی using میشه یا کلاس؟ یعنی در اینجا این using برای شی myRead هست یا برای کلاس StreamWriter ؟
    البته در اینجا چون کلاس File بصورت static هست ، پس به myRead نمیشه گفت که یک شی هست . درسته؟ در واقع یک متغییر هست. درسته؟
     
    آخرین ویرایش: ‏11 می 2016
    نوشته شده توسط SajjadKhati در ‏11 می 2016
  11. SajjadKhati

    SajjadKhati کاربر فعال <A href="http://forum.majidonline.com/f

    ارسال‌ها:
    630
    تشکر شده:
    152
    امتیاز دستاورد:
    43
    یه سئوال دیگه اینکه چجوری هست برای ساخت بعضی از اشیاء ، از new استفاده میکنیم (new هم اگه اشتباه نکنم به شی مون ، حافظه اختصاص میده) ولی بعضی موقع نه؟ مثل این :

    کد (Text):

    int x;
    x = 5;
     

    هر چند تا قبل از خط دوم ، چون حافظه ای بهش اختصاص داده نشد ، مقدار (حتی مقدار اولیه که صفر هست) نداره ولی بالاخره بدون استفاده از new برامون از اون کلاس شی ایجاد شد در صورتی که برای ایجاد خیلی از اشیاء دیگه ، باید از new استفاده کنیم
    تفاوت بین ساخت این نوع شی (بدون new) و اشیایی که با new مسیازیم چیه و از کجا بدونیم کجا میتونیم بدون new هم شی ایجاد کنیم؟
    هر چند در اینجا میشه با new هم همین شی x رو ایجاد کرد ولی الان ساخت اش بدون new منظورم هست
     
    نوشته شده توسط SajjadKhati در ‏11 می 2016
  12. the_king

    the_king مدیرکل انجمن

    ارسال‌ها:
    10,201
    تشکر شده:
    10,110
    امتیاز دستاورد:
    113
    البته این مثال شما استفاده کاملی از قابلیت using نیست چون درست بعد از using با ; بلوک رو بسته، یعنی { و } رو نداره، ولی در کل این using باعث شده که myRead در سطر بعدی کد دیگه وجود نداشته باشه و Dispose بشه.

    کد همون تاپیک تغییر رنگ پس زمینه فرم در سی شارپ رو ببینید، برای ایجاد کردن شی از فرم ColorDialog از using استفاده کرده ام.
    این using ارتباطی با اون using فضای نام نداره. این using یک فرمان ئه، برای اشیاء ای بکار میره که منابعی بهشون تخصیص داده میشه و باید هر چه زودتر که کار تون باهاش تمام شد آزاد بشوند، این جور اشیا کلاس شون Disposable اند، یعنی متدی به نام Dispose دارند.
    StreamWriter و Bitmap و Font و Form و ... Disposable هستند و هر وقت کارتان باهاشون تمام شد در سریعترین زمان ممکن باید نابودشون کنید تا منابع محدود سیستم رو بی خودی اشغال نکنند.

    ممکنه کد نویس فراموش کنه که وقتی کارش با این اشیاء تموم شد متد Dispose رو فراخوانی کنه. using راهنمای کامپایلر ئه که بفهمه شما تا کجای کد به اون شیء احتیاج دارید.
    using به شما اجازه میده که داخل بلوک خودش از شیء استفاده کنید، وقتی از بلوک اش خارج شدید خودکار Dispose رو فراخوانی می کنه و منابع شیء بزودی آزاد میشه. شما ممکنه توی اون بلوک { و } اش صد ها سطر کد دیگه بنویسید ولی به هر حال وقتی
    از اون بلوک خارج شدید شیء مورد نظر نابود شده محسوب میشه.
    کد (Text):

                using (var f = new Form())
                {
                    //Your Code
                    //Your Code
                    //Your Code
                }
     
    using فقط برای اشیاء Dispose شدنی قابل استفاده است و مثلا شما نمی توانید یک متغیر int رو using کنید :
    کد (Text):

    [COLOR="#FF0000"]            using (var x = new int())
                {
                    //Your Code
                    //Your Code
                    //Your Code
                }
    [/COLOR]
    یا نمی توانید شیء ای که داخل بلوک using تعریف شده بوده در بیرون بلوک استفاده کنید چون بیرون بلوک وجود نداره :
    کد (Text):

                using (var f = new Font("Tahoma", 14f))
                {
                    //Your Code
                    //Your Code
                    //Your Code
                }
    [COLOR="#FF0000"]            button1.Font = f;[/COLOR]
     
    و البته در نظر بگیرید که مدیریت منابع و حافظه در #C با Garbage Collector زبان ئه و اینطوری نیست که چون Dispose رو فراخوانی کردید همان لحظه شیء رو نابود کنه. ممکنه اینکار با تاخیر انجام بشه.
     
    نوشته شده توسط the_king در ‏11 می 2016
    SajjadKhati از این پست تشکر کرده است.
  13. SajjadKhati

    SajjadKhati کاربر فعال <A href="http://forum.majidonline.com/f

    ارسال‌ها:
    630
    تشکر شده:
    152
    امتیاز دستاورد:
    43
    آها
    ممنون متوجه شدم
    پس انگار همون کار متغییر محلی و بلاک ها رو میکنه که
    خوب نمیشه بجای using از بلاک ها استفاده کنیم؟ یعنی دقیقا استفاده از using و استفاده از بلاک ها عملکردشون شبیه هم هست دیگه؟ :

    کد (Text):

    private void button1_Click(object sender, EventArgs e)
            {
                {
                    int x = 10;
                }
                MessageBox.Show(X.ToString());
            }
     

    کد بالا هم شی x موقع فراخونی اش در دسترس نیست
    پست 111 رو هم جواب بدین ممنون میشم
    :rose:
     
    نوشته شده توسط SajjadKhati در ‏11 می 2016
  14. the_king

    the_king مدیرکل انجمن

    ارسال‌ها:
    10,201
    تشکر شده:
    10,110
    امتیاز دستاورد:
    113
    نه، مثل هم نیست، اون بلوک کدی که شما ساخته اید مستقل از اینکه چه اشیاء ای داخلش تعریف کنید هیچ کاری با Dispose نداره.
    این یک کلاس Disposable ئه :
    کد (Text):

            public class CC : IDisposable
            {
                public void Dispose()
                {
                    MessageBox.Show("Dispose");
                }
            }
     
    دو تا دکمه روی فرم قرار بدهید و خودتان تفاوت شان را امنحان کنید :
    کد (Text):

            private void button1_Click(object sender, EventArgs e)
            {
                {
                    var x = new CC();
                }
            }

            private void button2_Click(object sender, EventArgs e)
            {
                using (var x = new CC())
                {
                }
            }
     
     
    نوشته شده توسط the_king در ‏11 می 2016
    SajjadKhati از این پست تشکر کرده است.
  15. the_king

    the_king مدیرکل انجمن

    ارسال‌ها:
    10,201
    تشکر شده:
    10,110
    امتیاز دستاورد:
    113
    اشتباه نکنید، تا سطر دوم شیء ای ایجاد نشده، شما یک متغیر به نام x تعریف کرده اید که هنوز مقداری داخلش نیست، مقدار همون شیء ئه.

    اینجا 5 از دید کامپایلر یک عدد int است و خودش مستقیما یک شیء از نوع کلاس System.Int32 محسوب میشه، به همین جهت ئه که new لازم نداره.
    در کل برای هر کلاسی میشه تعریف کرد که چه نوع داده هایی رو به نوع خودش تبدیل کنه، یعنی فرضا مقدار عددی 5 به یک شیء از نوع فلان تبدیل بشه.
    همیشه جایگزین new نمیشه، فقط مناسب کلاس هایی است که با یک مقدار داده ای ساده قابل ایجاد باشند. این خلاصه نویسی نیست که new رو حذف کنند.
    با public static implicit operator میتوانید تعریف کنید که فلان نوع داده به چه نحوی به نوع داده فلان تبدیل بشه، مثلا int بصورت ضمنی چطور به CC قابل تبدیل ئه.

    کد (Text):

            public class CC
            {
                private int _value = 0;

    [COLOR="#0000FF"]            public static implicit operator CC(int value)[/COLOR]
                {
                    var x = new CC();
                    x._value = value;
                    return x;
                }
            }
     
    و نتیجه اش اینطور کدی میشه که کامپایلر می دونه چطور مقدار int رو به CC تبدیل کنه.
    کد (Text):

            private void button1_Click(object sender, EventArgs e)
            {
                CC x = 5;
            }
     
     
    نوشته شده توسط the_king در ‏11 می 2016
    SajjadKhati از این پست تشکر کرده است.
  16. SajjadKhati

    SajjadKhati کاربر فعال <A href="http://forum.majidonline.com/f

    ارسال‌ها:
    630
    تشکر شده:
    152
    امتیاز دستاورد:
    43

    ممنون
    ولی من متوجه نشدم که کد دکمه دوم ، چجوری باعث فراخونی متد Dispose() شد؟
    با ایجاد شی از کلاس CC در دکمه ی دوم (یا حتی دکمه ی اول) ، متد سازنده ی کلاس پدر که IDisposable هست اجرا میشه . حالا برای فراخونی متد Dispose() باید خودمون فراخونی اش کنیم که نکردیم . از طرفی هم این یک متد سازنده ی کلاس CC نیست که اتوماتیک موقع ایجاد شی ، اجرا بشه . پس چجوری توی کد دکمه ی دوم اجرا شد؟

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

    بعد اینکه آیا کلاس ها قابل تبدیل شدن به هم هستند؟ در واقع آیا اشیاء قابل تبددیل شدن به هم هستند؟ یعنی هر شی ای قابل تبدیل شدن به شی دیگه هست؟ . چون شی عددی قابل تبدیل شدن به رشته و برعکس هست ، آیا میتونیم مثلا شی ای از کلاس Brush رو مثلا تبدیل به شی ای از کلاس Color کرد؟ و ... ؟
    البته قضیه ی کلاس Convert رو میدونم و منظورم استفاده از اون کلاس نیست
    آخه مثلا وقتی میخوام در رویدادی ، آبجکت Sender رو به کلاس های زیرشاخه اش مثلا کنترل خاصی تبدیل کنیم (کستینگ) ، برای تبدیل اش ، قبل اش پرانتز باز میکنیم که باعث تبدیل شی ای به شی دیگه میشه . از این جور چیزا منظورمه
     
    آخرین ویرایش: ‏11 می 2016
    نوشته شده توسط SajjadKhati در ‏11 می 2016
  17. SajjadKhati

    SajjadKhati کاربر فعال <A href="http://forum.majidonline.com/f

    ارسال‌ها:
    630
    تشکر شده:
    152
    امتیاز دستاورد:
    43

    آها ممنون متوجه شدم :rose:
    دقیقا مثل این کد میمونه :

    کد (Text):

    string myText = textBox1.Text;
     
    در اینجا چون سمت راست یک مقدار که همون شی ای از کلاس مورد نظر (String) که گفتید داره ، یا در واقع شی myText مون که مقدار داره ، پس وقتی مقداری برای شی یک کلاس تعریف میشه ، لازم نیست که با کلمه کلیدی new براش حافظه اختصاص بدیم خودمون و کمپایلر خودش این کار رو میکنه (چون مقدار یا در واقع شی ای از اون کلاس براش در نظر گرفته شده)

    یا مثلا مثل این :

    کد (Text):

    int myText = Convert.ToInt32(textBox1.Text);
     
     
    نوشته شده توسط SajjadKhati در ‏11 می 2016
  18. the_king

    the_king مدیرکل انجمن

    ارسال‌ها:
    10,201
    تشکر شده:
    10,110
    امتیاز دستاورد:
    113

    چه چیزی در عملکرد using براتون مبهم ئه؟ اینکه کامپایلر بتونه یک روال خودکار داشته باشه مبهمه یا اینکه یک متدی public ای به اسم Dispose رو بتونه فراخوانی کنه؟
    IDisposable کلاس نیست، Interface ئه، برای همین با I شروع میشه که موقع کد نویسی مشخص بشه که Interface ئه، یادآوری شاید لازم باشه که Interface ها برخلاف کلاس ها خودشون هیچ کد پیاده سازی ای ندارند، اسم و مشخصات متد رو دارند ولی فقط پروتوتایپ دارند، پیاده سازی شون
    فقط توی کلاسی موجود ئه که ازشون ارث بری می کنه و از Interface والد هیچ عملیاتی رو به ارث نمی برند، حتی یک سطر کد اجرایی.

    فقط مقدار ئه که تبدیل میشه، کلاس Class1 همیشه Class1 ئه، مقدار نیست که به کلاس دیگه ای تبدیل بشه.
    Casting صرفا راهنمای کامپایلر ئه، این حقیقتا تبدیل نوع داده نیست، شما به عنوان کد نویس می دانید که اون sender چه نوعی است ولی کامپایلر نمی دونه، با Casting راهنمایی ای اش می کنید که بفهمه که در اون قسمت کد با چه نوع داده ای کار می کنه.
    از نظر کامپایلر sender یک object ئه، متد های کنترل رو نشون نمیده چون اطلاعات اش از شیء مورد نظر در حد object ئه، شما راهنمایی اش می کنید وگرنه شیء این وسط تغییر نوع داده نمیده. اگر شما تو Casting اشتباه کنید و نوع داده اشتباهی
    رو بکار ببرید برنامه با خطا متوقف میشه.
    شما می توانید Brush رو به Color یا Form یا Font یا هر نوع دیگری تبدیل کنید، به شرطی که متدی بنویسید که این تبدیل رو انجام بده، هر چقدر هم به ظاهر غیر منطقی باشه همچنان منطق تبدیل رو شما تعیین می کنید نه کامپایلر.
     
    نوشته شده توسط the_king در ‏11 می 2016
    SajjadKhati از این پست تشکر کرده است.
  19. SajjadKhati

    SajjadKhati کاربر فعال <A href="http://forum.majidonline.com/f

    ارسال‌ها:
    630
    تشکر شده:
    152
    امتیاز دستاورد:
    43

    ممنون آقا علی :rose:
    اینکه یک متدی public ای به اسم Dispose رو بتونه فراخوانی کنه ، برام مبهم هست
    البته من با اینترفیس ها آشنا نیستم اگه ساختار اینترفیس باعث این فراخونی متد در کلاس CC میشه!
    ولی اگه ساختارش شبیه کلاس باشه ، مثلا برای فراخونی همچین متد Dispose() در کلاس CC ، باید اول شی ایجاد کرد از این کلاس و بعد هم متد موزذ نظر رو فراخونی کرد یعنی این جوری باید نوشت تا این متد در کلاس های معمولی اجرا بشه :

    کد (Text):

    using (var x = new CC())
                {
                    x.Dispose();
                }
     

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

    کد (Text):

    using (var x = new CC())
                {
                }
     
    باعث فراخونی متد Dispose() میشه؟
     
    نوشته شده توسط SajjadKhati در ‏11 می 2016
  20. the_king

    the_king مدیرکل انجمن

    ارسال‌ها:
    10,201
    تشکر شده:
    10,110
    امتیاز دستاورد:
    113
    شیء رو که شما تو کدتون می سازید، کامپایلر که لازم نداره شیء بسازه، شیء وجود داره. فقط می مونه فراخوانی متد Dispose اش.
    شما چون داخل بلوک using فراخوانی Dispose نمی بینید از اجرا شدنش تعجب می کنید؟
    پس چطور قبول می کنید که وقتی i به 10 رسید از حلقه for درمیاد؟ مگه توی این حلقه if و break ای هست که از حلقه در بیاد؟
    کد (Text):

                for (int i = 0; i < 10; i++)
                {
                }
     
     
    نوشته شده توسط the_king در ‏12 می 2016
    SajjadKhati از این پست تشکر کرده است.

به اشتراک بگذارید