PDA

View Full Version : چرا متد Add در لیست باکس متد Equals شی من را فراخوانی می کند ؟



WindowsXp
دوشنبه 12 دی 1390, 02:27 صبح
سلام دوستان
من یک کلاس دارم این شکلی :
class Student
{
public string Firstname { get; set; }
public string LastName { get; set; }

public override string ToString()
{
return String.Format("{0}-{1}",Firstname,LastName);
}
public override bool Equals(object obj)
{
bool fn = (Firstname == (obj as Student).Firstname);
bool ln = (LastName == (obj as Student).LastName);
return fn && ln;

}
}
در مرحله بعد میام یک فرم جدید درست می کنم و روش یک لیست باکس ، دو تا تکس باکس و یک دونه دکمه میذارم .
و این کد رو برای دکمم می نویسم :

private void button1_Click(object sender, EventArgs e)
{
Student s1 = new Student { Firstname = textBox1.Text, LastName =textBox2.Text };
listBox1.Items.Add(s1);
}

وقتی برنامه اجرا میشه و روی محتویات تکس باکس ها رو مینویسم و .. و در نهایت روی دکمه کلیک می کنم برنامه ارور میده و خطی که ارور داده متد Equals از کلاس Student هستش .
این یک سوال تحقیقاتی هستش نه عملیاتی ، میخوام بدونم متد Add چرا متد Equals رو از شی من صدا میزنه ؟

سوداگر
دوشنبه 12 دی 1390, 03:18 صبح
شما در متد add مربوط به لیست باکس باید s1.Firstname + s1.Lastname را وارد کنید(اگر میخواهید که اسم و فامیلی در یک سطر قرار بگیرند)

WindowsXp
دوشنبه 12 دی 1390, 04:37 صبح
من که نمیخوام String داخل لیست باکس ذخیره کنم !:اشتباه:
میخوام اشیائی از جنس Student ذخیره کنم !

rahmatr
دوشنبه 12 دی 1390, 05:41 صبح
این یک سوال تحقیقاتی هستش نه عملیاتی ، میخوام بدونم متد Add چرا متد Equals رو از شی من صدا میزنه ؟
این سورس متد Add است :

public int Add(object item)
{
this.owner.CheckNoDataSource();
int num = this.AddInternal(item);
this.owner.UpdateHorizontalExtent();
return num;
}

private int AddInternal(object item)
{
if (item == null)
{
throw new ArgumentNullException("item");
}
...
...
...

}


می بینید که در خط اول متد AddInternal شرط item == null چک شده و همین عبارت متد Equals شما را صدا می زند.

WindowsXp
دوشنبه 12 دی 1390, 05:44 صبح
:متعجب: :متعجب: :متعجب: :متعجب: :متعجب: :متعجب: :متعجب:
ایجوری نمیشه. ختما باید پارامترهای ورودی متد add مطابق همون چیزی باشه که براش تعریف کرده اند. شما نمیتوانید هر شیئی از هر نوعی را درون آن بریزید!!!!
خب یک سر به ویژوال استیودیو بزنید لطفا ببینید متد Add پارامتر ورودیش از چه جنسیه !

WindowsXp
دوشنبه 12 دی 1390, 14:16 عصر
این سورس متد Add است :

public int Add(object item)
{
this.owner.CheckNoDataSource();
int num = this.AddInternal(item);
this.owner.UpdateHorizontalExtent();
return num;
}

private int AddInternal(object item)
{
if (item == null)
{
throw new ArgumentNullException("item");
}
...
...
...

}


می بینید که در خط اول متد AddInternal شرط item == null چک شده و همین عبارت متد Equals شما را صدا می زند.

خیلی ممنون این جواب سوال من هست اما یک سوال دیگه برام پیش اومد !
اگر item == null منجر به صدا زده شدن Equals بشه یعنی null رو به عنوان پارامتر ورودی به Equals ارسال می کنه ؟
اما مشکل اینجاست که وقتی پروژه ی من توی متد Equals ِ شیِ Student ام خطا میده obj یعنی پارامتر ورودی اون متد null نیست یک شی از جنس DBnull هستش !
در مورد این DBnull میشه توضیح بدید ؟

rahmatr
دوشنبه 12 دی 1390, 16:28 عصر
اگر item == null منجر به صدا زده شدن Equals بشه یعنی null رو به عنوان پارامتر ورودی به Equals ارسال می کنه ؟
اما مشکل اینجاست که وقتی پروژه ی من توی متد Equals ِ شیِ Student ام خطا میده obj یعنی پارامتر ورودی اون متد null نیست یک شی از جنس DBnull هستش !
من اشتباه کردم. الان که تست کردم دیدم == باعث صدا زدن Equals نمی شود.

سورس Items.Add را به طور کامل بررسی کنید حتما جایی با DBnull مقایسه می شود.
برای دیدن سورس از Red Gate's .NET Reflector استفاده کنید (نسخه 6ش رایگانه).

WindowsXp
دوشنبه 12 دی 1390, 16:30 عصر
خیلی ممنون از راهنمائیتون :-(
مطمئنید Red Gate's .NET Reflector رایگان هستش ؟
من توی سایتش میگردم نسخه ی 6 اش نیست فقط 7 هست که اون هم پولیه !

rahmatr
دوشنبه 12 دی 1390, 16:52 عصر
اینجا را ببینید :
http://barnamenevis.org/showthread.php?205944-%D9%85%D8%B9%D8%B1%D9%81%DB%8C-%D8%A7%D8%A8%D8%B2%D8%A7%D8%B1-%DA%A9%D8%B1%DA%A9-%D8%A8%D8%B1%D8%A7%DB%8C-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%87%D8%A7%DB%8C-%D8%AF%D8%A7%D8%AA-%D9%86%D8%AA

WindowsXp
پنج شنبه 15 دی 1390, 01:03 صبح
من با توجه به Call Stack و یک برنامه ی Reflector به این نتیجه رسیدم :

ما صدا می کنیم

System.Windows.Forms.ListBox.ObjectCollection.Add( object item)

این متد این رو صدا می کنه :

System.Windows.Forms.ListBox.ObjectCollection.AddI nternal(object item)
این متد این رو صدا می کنه :
System.Windows.Forms.ListBox.NativeAdd(object item)
این متد این رو صدا می کنه :
System.Windows.Forms.ListControl.GetItemText(objec t item)
این متد این رو صدا می کنه :
System.Windows.Forms.Formatter.FormatObject(object value, System.Type targetType, System.ComponentModel.TypeConverter sourceConverter, System.ComponentModel.TypeConverter targetConverter, string formatString, System.IFormatProvider formatInfo, object formattedNullValue, object dataSourceNullValue)

این متد این رو صدا می کنه :
System.Windows.Forms.Formatter.IsNullData(object value, object dataSourceNullValue)


این متد این رو صدا می کنه :
object.Equals(object objA, object objB)
که با توجه به Override شدن متد Equals کلاس من متد Equals آبجکت متد Equal کلاس Student رو فراخوانی می کنه :

WindowsFormsApplication1.Student.Equals(object obj)
و پارامتری که برای تابع Equals ارسال میشه یک آبجکت از جنس DBNULL هستش که چون قابل Cast به Student نیست عبارت (obj as Student) مقدار null رو بر میگردونه .
سوال جدیدم اینه :
DBNULL چه ؟و اون وسط چی کار می کنه ؟