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

the_king

مدیرکل انجمن
ممنون استاد علی
ولی این تیکه از سئوالم هنوز باقی موند . ممنون میشم جواب بدین :
این پارامتر stringArg1 که داخل متد StringMethodClass1 تغییرش می دهید یک اشاره گر بوده به اون آرایه، یعنی testString و stringArg1 هر دو به یک آرایه اشاره می کردند. شما آمدید stringArg1 رو به یک آرایه دیگه اشاره اش داده اید :
کد:
             stringArg1 = newStr;
خوب این اتفاق که ربطی به testString نداره، اون یک اشاره گر دیگه است در متغیری در btnTestString_Click، شما با تغییر اشاره گر stringArg1 مقدار testString رو که عوض نمی کنید.
اما همانطور که دیدید در کد آخر تون وقتی محتویات آرایه ای که stringArg1 بهش اشاره می کنه تغییر می دهید همان آرایه ای تغییر می کنه که testString بهش اشاره کرده.

اگه بعد از عمل انتصاب ، به فرم اضافه کنیم ، توسط Garbage collector حذف میشه اون شی؟ :
کد:
            btnTest1 = new Button();
            btnTest2 = new Button();
            btnTest1.Location = new Point(6, 600);
            btnTest1.Text = "btnTest1";
            btnTest2.Location = new Point(90, 600);
            btnTest2.Text = "btnTest2";

            btnTest1 = btnTest2;
            btnTest1.Text = "salam";
            contGroupBoxTest1.Controls.Add(btnTest1);
طبیعتا شی ای که قبلا ساخته اید ولی در متغیر نگه اش نداشته اید رو نمی توانید بعدا به فرم اضافه کنید.
اگه منظورتون شیء دکمه اول ئه، بله اگه روی فرم اضافه اش نکرده باشید حذف میشه، البته ممکنه با تاخیر انجام بشه ولی چون دیگه اشاره گری بهش نیست این اتفاق براش می افته، اما شیء دکمه دوم نه.
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
سلام
ممنون استاد علی
میگم در کد زیر ، یه عضو protected در کلاس پدرتعریف شد . چرا در کلاس فرزند ، وقتی شی ای از کلاس پدر ایجاد میکنم ، به این عضو دسترسی نداره ولی وقتی کلمه ی کلیدی base رو از توی کلاس فرزند بکار میبرم ، بهش دسترسی داره؟ !!! مگه کلمه کلیدی base ، همون شی ای از کلاس پدر نیست؟ مثل this که شی ای از خود همون کلاس هست؟ پس نباید وقتی از کلاس پدر شی درست میکنیم و یا کلمه ی 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
    }
    }
}

خط آخر ، اشتباست و دسترسی نداره !
 

the_king

مدیرکل انجمن
سلام
ممنون استاد علی
میگم در کد زیر ، یه عضو protected در کلاس پدرتعریف شد . چرا در کلاس فرزند ، وقتی شی ای از کلاس پدر ایجاد میکنم ، به این عضو دسترسی نداره ولی وقتی کلمه ی کلیدی base رو از توی کلاس فرزند بکار میبرم ، بهش دسترسی داره؟ !!! مگه کلمه کلیدی base ، همون شی ای از کلاس پدر نیست؟ مثل this که شی ای از خود همون کلاس هست؟ پس نباید وقتی از کلاس پدر شی درست میکنیم و یا کلمه ی 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
    }
    }
}

خط آخر ، اشتباست و دسترسی نداره !
درسته که Test1 وارث کلاس Form1 ئه، ولی برای دسترسی به myDinamicVar4 ای مجوز داره که در base خودشه، نه همه اشیاء Form1
این protected ارتقاء ای برای private ئه، در همون حد که متغیر داخل شیء وارث اش دیده بشه. دسترسی به سایر اشیاء تعمیم پیدا نمی کنه. اون form1Obj یک شیء دیگه است و مستقل.
 

SajjadKhati

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

ممنون
ولی من قشنگ متوجه نشدم :(
سئوال من اینه :
مگه وقتی که از شی base استفاده کنیم با زمانی که شی ای از کلاس پدر خودمون بسازیم ، فرقی داره؟
علی الظاهر نباید فرق داشته باشه
پس چرا عضو protected در کلاس پدر ، وقتی در کلاس فرزند ، base مینویسیم میاد ولی از همون کلاس فرزند ، شی از کلاس پدر درست میکنیم ، نمیاره؟
 

the_king

مدیرکل انجمن
ممنون
ولی من قشنگ متوجه نشدم :(
سئوال من اینه :
مگه وقتی که از شی base استفاده کنیم با زمانی که شی ای از کلاس پدر خودمون بسازیم ، فرقی داره؟
علی الظاهر نباید فرق داشته باشه
پس چرا عضو protected در کلاس پدر ، وقتی در کلاس فرزند ، base مینویسیم میاد ولی از همون کلاس فرزند ، شی از کلاس پدر درست میکنیم ، نمیاره؟
کلاس فرقی نداره اما برای دسترسی protected بین ایندو فرق وجود داره، protected به شما مجوز دسترسی به اون base رو میده نه همه Form1 ها. protected کاری به این نداره که فلان شیء از چه نوع کلاسی ئه، دسترسی هر instance اش صرفا برای اشیاء وارث همون instance محدود شده، شما از یک instance وارث دیگه نمی توانید به متغیری دسترسی داشته باشید که از یک instance دیگه است، حتی اگه از همون نوع کلاس باشه.
این تعریف دسترسی protected ئه، وگرنه مساله تفاوت کلاس base با هر Test1 ای نیست. شما با base و بدون base صرفا به myDinamicVar4 ای دسترسی دارید که برای همون شیء Test1 وجود داره و کد داخلش اجرا میشه. اون شیء که شما از کلاس form1Obj ساخته اید، از جنس کلاس والد Test1 ئه ولی این شیء هیچ ارتباطی با دسترسی protected برای شیء ای که شما اون کد رو داخل اجرا می کنید نداره، برای همین protected برای دسترسی اون کد به اون form1Obj.myDinamicVar4 کافی نیست. این محدودیت protected ئه.
 

SajjadKhati

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

SajjadKhati

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

کد:
string a = "salam";
string b = "salam";

یعنی a و b در کد بالا ، هر دو به یه خونه اشاره میکنن یا نه؟
 

the_king

مدیرکل انجمن
سلام
ممنون استاد علی
برای ایندکسرها ، اگه طولش رو بخوایم برگردونیم ، باید خودمون جداگانه تابع بنویسیم؟
اگه منظورتون از indexer اون پروپرتی [] this ئه، طول کاری با indexer نداره، بله، یک مفهوم مستقل ئه و حتی foreach هم کاری با اون تابع یا پروپرتی طول ای که میسازید نداره.
یه سئوال دیگه اینکه چرا وقتی از ArrayList شی ایندکسر درست میکنیم ، توی حلقه ی foreach به عنوان کالکشن میشناسه ولی وقتی خودمون یه ایندکسر درست میکنیم ، توی این حلقه نه به عنوان کالکشن و نه آرایه نمیشناسه؟ راهی هست که کاری کنیم توی حلقه ی foreach بشناسه و قبول کنه؟

هیچ ارتباطی بین indexer و enumerable که دومی در foreach استفاده میشه وجود نداره، ایندو قابلیت کاملا مستقل از هم اند، یک کلاس می تونه indexer داشته باشه ولی enumerable نباشه یا برعکس. ArrayList رو می توانید در foreach بکار می برید نه به این خاطر که indexer داره، به این دلیل که enumerable ئه و از اینترفیس IEnumerable ارث بری کرده. یک متد GetEnumerator داره که اون این قابلیت رو بهش میده، هیچ ربطی به indexer نداره. foreach هیچ کاری با indexer نداره و اصلا سراغش نمیره. شما اول باید یک کلاس جداگانه بسازید که از IEnumerator ارث بری کنه. اون کلاسی است که foreach از اطلاعاتش استفاده می کنه، نه indexer و نه طول، حالا چه Count یا Length
در اون متد GetEnumerator که جزئی از اینترفیس IEnumerable ئه شما باید شیء ای از این کلاس IEnumerator که خودتان پیاده سازی کرده اید بسازید و تحویل بدهید.
foreach در ابتدای پیمایش اول ممکنه Reset اون کلاس IEnumerator رو فراخوانی کنه، مخصوصا بعد از تغییر در مجموعه اینکار رو می کنه، بعد در هر مرحله پیمایش با MoveNext میره سراغ اندیس بعدی (موقع شروع کار و بعد از Reset اندیس حتی روی خانه اول هم نیست، مثلا 1- ئه) و با Current مقدار آیتم اون اندیس فعلی رو تحویل حلقه foreach میده (و نه با indexer)
کد:
    public class MyClass : IEnumerable<string>
    {
        private string[] _array = new string[] { "AAA", "BBB", "CCC", "DDD" };

        public class Enumerator : IEnumerator<string>
        {
            private MyClass _obj;
            private int _index = -1;

            public Enumerator(MyClass obj)
            {
                _obj = obj;
            }

            public string Current
            {
                get
                {
                    return _obj._array[_index];
                }
            }

            public void Dispose()
            {               
            }

            object System.Collections.IEnumerator.Current
            {
                get
                {
                    return _obj._array[_index];
                }
            }

            public bool MoveNext()
            {
                _index++;
                return (_index < _obj._array.Length);
            }

            public void Reset()
            {
                _index = -1;
            }
        }

        public IEnumerator<string> GetEnumerator()
        {
            return new Enumerator(this);
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return new Enumerator(this);
        }
    }
 

SajjadKhati

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


کد:
object a = "String";
            string b = "String";
            string c = typeof(string).Name;
            MessageBox.Show((b == c).ToString());
            MessageBox.Show((a == b).ToString());
            MessageBox.Show((a == c).ToString());

البته در سومی ، اول ، نوع a به رشته تبدیل و بعد مقایسه بشه ، جوابش ترو میشه
ولی من خوب اینو درک نکردم که چرا پس حتی بدون تبدیل نوع a ، با رشته ی دومی در کد بالا برابر شد اما با همین نوع رشته در سومی نابرابر !
 

the_king

مدیرکل انجمن
ممنون استاد علی
این کد چرا این طوری هه ؟ یعنی چرا جواب آخری فلس میشه؟ در صورتی که دو تای اول ترو میشه پس اتوماتیک نتیجه ی آخری باید ترو بشه (هر چند اولی آبجکت باشه ولی با رشته از نوع دومی برابره ولی با سومی که بازم رشته هه برابر نیست) :


کد:
object a = "String";
            string b = "String";
            string c = typeof(string).Name;
            MessageBox.Show((b == c).ToString());
            MessageBox.Show((a == b).ToString());
            MessageBox.Show((a == c).ToString());

البته در سومی ، اول ، نوع a به رشته تبدیل و بعد مقایسه بشه ، جوابش ترو میشه
ولی من خوب اینو درک نکردم که چرا پس حتی بدون تبدیل نوع a ، با رشته ی دومی در کد بالا برابر شد اما با همین نوع رشته در سومی نابرابر !
فراموش نکنید که string یک reference type ئه که همانند value type ها مقدار داخل رشته رو مقایسه می کنه. تلاش شده که این رفتار value type ها در مورد string بصورت کامل شبیه سازی بشه ولی کامپایلر خیلی هوشمند نیست و برخی مواقع به ذات reference type ها بر می گرده. اگر طوری کد نویسی کنید که کامپایلر وادار به استفاده از مقایسه reference type بشه دیگه کاری با مقدار داخل رشته ها نخواهد داشت و همانند سایر reference type ها reference شون رو مقایسه خواهد کرد، مثل مقایسه دو تا اشاره گر می مونه.
این چند تا مثال رو اجرا کنید :
کد:
            string a = "String";
            string b = "Str" + "ing";
            MessageBox.Show(object.ReferenceEquals(a, b).ToString());

کد:
            string a = "String";
            string b = a.Replace("S", "S");
            MessageBox.Show(object.ReferenceEquals(a, b).ToString());

کد:
            string a = "String";
            string b = new string(a.ToCharArray());
            MessageBox.Show(object.ReferenceEquals(a, b).ToString());

کامپایلر صرفا در مثال های خیلی ساده رشته های یکسان رو تشخیص میده و بهشون reference یکسان میده، این فقط یک تلاش ابتدایی کامپایلر ئه.
شما با مقایسه object با string کامپایلر رو وادار به مقایسه reference type می کنید. در مورد انتساب ساده ای مثل ;"String" = کامپایلر به اندازه کافی هوشمند هست و reference ها رو یکسان در نظر می گیره ولی کامپایلر اونقدر هوشمند نیست که بتونه شباهت typeof(string).Name رو با "String" تشخیص بده و طبق ذات string دو تا reference جداگانه تخصیص میده. با (string) به کامپایلر بفهمانید که می خواهید رشته رو با رشته مقایسه کنید :
کد:
            object a = "String";
            string c = typeof(string).Name;
            MessageBox.Show(((string)a == c).ToString());
و یا اصلا مستقیما از Equals ئه string استفاده کنید :
کد:
            object a = "String";
            string c = typeof(string).Name;
            MessageBox.Show(string.Equals(a, c).ToString());
وگرنه شما دارید عملا object.ReferenceEquals رو بکار می برید :
کد:
            object a = "String";
            string c = typeof(string).Name;
            MessageBox.Show(object.ReferenceEquals(a, c).ToString());
 

SajjadKhati

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

SajjadKhati

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


کد:
public dynamic[,] AddToDynamicArray<myType, valueType>(myType[,] entryArray,params valueType[] data)
        {
            int zeroArrayLength = entryArray.GetLength(0);
            dynamic[,] copyArray = new dynamic[zeroArrayLength + 1, 3];

            for (int i = 0; i < copyArray.GetLength(0); i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    if (i + 1 == copyArray.GetLength(0))
                        copyArray[i, j] = data[j];
                    else
                        copyArray[i, j] = entryArray[i, j];
                }
            }

            return copyArray;
        }





private void btnArrayCopy_Click(object sender, EventArgs e)
        {
            string[,] a = { { "a", "b", "c" } };
            foreach (var item in this.AddToDynamicArray<string, int>(a, 1, 5, 10))
            {
                MessageBox.Show(item.ToString());
            }
        }

تابع ، آرایه ای رو میگیره و کپی میکنه و آخر آرایه هم ، مقادیری که توی ورودی تابه بصورت پارامز بهش دادیم ، رو به خونه ی آخر آرایه میچسبونه و برمیگردونه
جای سئوال و تعجب برام اینجاست که مقدار بازگشتی تابع و همینطور اون آرایه ی copyArray داخل تابع رو dynamic تعریف کردم ولی هم مقدار رشته و هم مقدار عدد (یعنی دو نوع متفاوت) رو پذیرفت و مشکلی هم پیش نیومد !!
من انتظار داشتم ارور run time بگیرم ولی کار کرد !! . مگه dynamic تا این حد انعطاف پذیره؟ !!
بعد اینکه ، من میخوام در تابع بالا ، هم مقدار بازگشتی تابع و هم آرایه ی copyArray ، از نوع آرایه ای از myType باشه ولی اگه این دوتا رو از این نوع بگیرم ، نمیشه از 2 نوع متفاوت در آرایه ی copyArray ذخیره کنم (هم نوع myType و هم نوع valueType) واگه بجز این عمل کنم ، در کد خط :

کد:
copyArray[i, j] = data[j];

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

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
آقا ، این چرا اشتباه نمیده (منظورم ارور کمپایلر هست نه run time) و میذاره بنویسیم :

کد:
dynamic a = "salam";
            int h = a;

یعنی میذاره نوع دینامیک رو توی هر چیز دیگه ای مثل int بریزیم
ولی یه متد نوشتم که آرایه ای از دینامیک ها رو برمیگردونه اما اونجا نمیشه بریزم توی نوعی بجز دینامیک؟ چرا؟ یعنی چرا این کد که آرایه ای از دینامیک ها رو برمیگردونه ، کمپایلر ازش خطا میگیره ولی از بالایی نمیگیره؟ :


کد:
string[,] findedText = this.FindPatterns("85 salam 435.25", "\\d");
 

the_king

مدیرکل انجمن
سلام
ممنون استاد علی
اینایی که میگم ، درسته؟ :
کلمه ی کلیدی dynamic ، باعث میشه کمپایلر کنترل رو بده به برنامه نویس و همه چیز رو خود برنامه نویس مدیریت کنه .یعنی اگه خطایی وجود داشته باشه ، توی موقع اجرا داده میشه . درست هه؟
مثل زبان های اسکریپتی . درست هه؟
یعنی برخلاف کلمه ی var که کمپایلر همه کاراشو میکنه ، dynamic کارها میافته تو دست برنامه نویس . درست هه؟
نه، صحبت کنترل و همه چیز و همه کارا نیست، برنامه نویس در هنگام نوشتن کد روال رو مشخص می کنه وگرنه در هنگام اجرای کد که نقشی نداره. dynamic شبیه یک متغیر از نوع object ئه.
شما چطور در یک متغیر object می توانید یک string یا int یا array یا TextBox رو قرار دهید، در dynamic هم همینطوره. در var نوع داده متغیر ثابت بود و در زمان کامپایل باید حتما بصورت خودکار مشخص می شد و قابل تشخیص بود.
اما در مورد dynamic نوع داده برخلاف var بجای مشخص شدن در زمان کامپایل در زمان اجرا و با دریافت هر مقدار جدید بصورت خودکار تعیین میشه یا حتی تغییر می کنه.
تفاوت کاربرد dynamic با object تنها در اینه که در موقع کامپایل شدن کد، نوع داده مقادیر dynamic چک نمیشه، فرضا اگر جای یک پارامتر int متغیر dynamic بکار برده بشه، کامپایلر خطا نمیده که این object ئه و int نیست و اول باید به int تبدیل بشه و مجبور باشید (int) رو در کد اضافه کنید. dynamic فرض رو بر این میگیره که اجرا وقتی به اون قسمت کد رسید فرضا یک مقدار int داخل متغیر هست. حالا در زمان اجرا که به اون قسمت از کد رسید، اگر مقدار معادل یک int نباشه به هر حال خطا بروز می کنه. یعنی اگر اون متغیر در جایی بجای نوع داده نامناسبی بکار برده بشه dynamic بودن جلوی بروز خطا رو نمیگیره.
 

the_king

مدیرکل انجمن
آقا ، این چرا اشتباه نمیده (منظورم ارور کمپایلر هست نه run time) و میذاره بنویسیم :

کد:
dynamic a = "salam";
            int h = a;

یعنی میذاره نوع دینامیک رو توی هر چیز دیگه ای مثل int بریزیم
ولی یه متد نوشتم که آرایه ای از دینامیک ها رو برمیگردونه اما اونجا نمیشه بریزم توی نوعی بجز دینامیک؟ چرا؟ یعنی چرا این کد که آرایه ای از دینامیک ها رو برمیگردونه ، کمپایلر ازش خطا میگیره ولی از بالایی نمیگیره؟ :


کد:
string[,] findedText = this.FindPatterns("85 salam 435.25", "\\d");
قضیه همون چک کردن نوع داده است، FindPatterns از دید کامپایلر میتونه هر نوع مقداری رو برگردونه و تا زمان اجرای کد تضمینی در کار نیست که حتما یک مقدار [,]string برگردونه. برای همین کامپایلر به ضمانت برنامه نویس احتیاج داره، باید یک cast ئه ([,]string) به کد اضافه کنید، درست بعد از = تا کامپایلر مطمئن بشه که شما خودتون صریحا ضمانت می کنید که در اون بخش کد FindPatterns یک [,]string رو بر می گردونه.
 

the_king

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


کد:
public dynamic[,] AddToDynamicArray<myType, valueType>(myType[,] entryArray,params valueType[] data)
        {
            int zeroArrayLength = entryArray.GetLength(0);
            dynamic[,] copyArray = new dynamic[zeroArrayLength + 1, 3];

            for (int i = 0; i < copyArray.GetLength(0); i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    if (i + 1 == copyArray.GetLength(0))
                        copyArray[i, j] = data[j];
                    else
                        copyArray[i, j] = entryArray[i, j];
                }
            }

            return copyArray;
        }





private void btnArrayCopy_Click(object sender, EventArgs e)
        {
            string[,] a = { { "a", "b", "c" } };
            foreach (var item in this.AddToDynamicArray<string, int>(a, 1, 5, 10))
            {
                MessageBox.Show(item.ToString());
            }
        }

تابع ، آرایه ای رو میگیره و کپی میکنه و آخر آرایه هم ، مقادیری که توی ورودی تابه بصورت پارامز بهش دادیم ، رو به خونه ی آخر آرایه میچسبونه و برمیگردونه
جای سئوال و تعجب برام اینجاست که مقدار بازگشتی تابع و همینطور اون آرایه ی copyArray داخل تابع رو dynamic تعریف کردم ولی هم مقدار رشته و هم مقدار عدد (یعنی دو نوع متفاوت) رو پذیرفت و مشکلی هم پیش نیومد !!
من انتظار داشتم ارور run time بگیرم ولی کار کرد !! . مگه dynamic تا این حد انعطاف پذیره؟ !!
بعد اینکه ، من میخوام در تابع بالا ، هم مقدار بازگشتی تابع و هم آرایه ی copyArray ، از نوع آرایه ای از myType باشه ولی اگه این دوتا رو از این نوع بگیرم ، نمیشه از 2 نوع متفاوت در آرایه ی copyArray ذخیره کنم (هم نوع myType و هم نوع valueType) واگه بجز این عمل کنم ، در کد خط :

کد:
copyArray[i, j] = data[j];

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

SajjadKhati

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

ممنون استاد علی
خوب پس نمیتونه تضمین بده که همه ی اعضاش string[,] باشن ، پس چطور توی کد اول میتونه تضمین بده که یه دینامیک (رشته) توی عدد ریخته بشه و اینجا چرا تضمین نمیگیره از کاربر؟
 

the_king

مدیرکل انجمن
ممنون استاد علی
خوب پس نمیتونه تضمین بده که همه ی اعضاش string[,] باشن ، پس چطور توی کد اول میتونه تضمین بده که یه دینامیک (رشته) توی عدد ریخته بشه و اینجا چرا تضمین نمیگیره از کاربر؟
کد اول تضمین نمی کنه، کامپایلر هم از این بابت ایراد نمی گیره، چون همانطور که عرض کردم چک کردن تطابق نوع داده برای dynamic در زمان اجرای کد ئه و نه زمان کامپایل. کامپایلر برای چک کردن تطابق داده متغیر های dynamic کاری انجام نمیده و نقشی در این مورد نداره و در نتیجه به ضمانت برنامه نویس هم احتیاجی نداره. اما برای سایر انواع داده این وظیفه کامپایلر ئه که موقع کامپایل شدن کد تطابق نوع داده رو چک کنه، چون در زمان اجرای کد دیگه چک کردنی در کار نیست.
 

SajjadKhati

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

سلام
ممنون استاد علی :rose:
ولی من خوب متوجه نشدم . یعنی متوجه شدم ولی سئوال منو فکر کنم درست نخوندین . منظورم اینه که در اون کدی که دادم ، یه چیز (شی) دینامیک روبدون تضمین ریختیم توی شی غیر دینامیک ولی توی کد دوم فقط در صورت تضمین و تبدیل ، تونستیم یه شی دینامیک رو توی غیر دینامیک بریزیم . توی هر دو ، شی دینامیک ریخته شدن توی غیر دینامیک اما یکی با تضمین و تبدیل و یکی دیگه بدون تضمین و تبدیل !!!

یه سئوال اینکه چرا وقتی کلاسی رو Generic تعریف میکنم که اون کلاس از کلاسی ارث برد ، همه ی کنترل (اشیاء) هایی که تعریف کردم ، از دسترس خارج میشه؟ یعنی وقتی کد رو بصورت زیر تعریف میکنم ، هر کنترل و شی ای که بصورت دستی توی Form1 گذاشتم (دکمه و لیبل و ...) ، شی اش دیگه در دسترس ام نیست و کمپایلر ارور میده که اشیاء در دسترس نیست . چرا؟ :


کد:
public partial class Form1<T> : Form

بعد اینکه ، شما با Regex ها کار کردین ، سئوالات مو درباره اش بپرسم؟

ممنون
 

SajjadKhati

کاربر فعال <A href="http://forum.majidonline.com/f
بعد اینکه ، توی قضیه ی جنریک ها ، چرا نمیتونم محدودیت نوع string و ... بذارم (فقط باید نوع کلی مثل class و struct و... رو مشخص کنم) ؟
 

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

بالا