SajjadKhati
کاربر فعال <A href="http://forum.majidonline.com/f
ادامه ی پست قبل :
و در رویدادی در فرم :
نکته ی مهم ای که درباره ی جنریک ها فهمیدم این بود که شی جنریک (مثلا Type در کلاس Sortable<Type> مثل شی this[0] در بالا) ، نمیتونه به یک کلاس تبدیل بشه و جنریک ها فقط میتونن به اینترفیس ها تبدیل بشن . دلیل اش بخاطر این میتونه باشه که نوع جنریک در زمان نوشتن کد و کمپایل ، مشخص نیست و کمپایلر نمیتونه متوجه بشه (که طبیعی هم هست) و زمان اجرا ، برای هر شی جنریک ، نوع اش مشخص میشه؟ درسته؟ ولی میتونه به اینترفیس تبدیل بشه چون پیاده سازی نداره . درسته؟
پس میشه گفت یکی از کاربرد اینترفیس ها ، توی جنریک هاست . درسته؟
چیزی که گفتم ، غلط بود یعنی در بدنه متد Sort ، پیش فرضش این نیست که در کلاس نوع جنریک (مثلا در کلاس Dog) ، اینترفیسی رو پیاده سازی کرده باشه
دوم اینکه طبق نکته ی بالا ، شی جنریک ها اصلا نمیتونن به کلاس تبدیل بشن
توی یه جا میبینیم ، برای متد Dispos ، کدی میدن (سایت استک اورفلو و مایکروسافت) که شی Managed رو رها میکنه . برای قسمت کدهای Unmanaged هم میدن . بعد توی توضیحاتش یکی میگه برای Managed کار نمیکنه و برای Unmagaed کار میکنه . یکی دیگه ، یه چیز دیگه میگه
اصلا متد Dispos رو ولش کنیم
حافظه ی Heap که دیگه اسنادش تو مایکروسافت فکر کنم باشه . خیلی جاهام درباره اش بحث کردن
اون اینترفیس هایی که نوشتم نمیدونم درباره ی چه قضیه ای هستن ، درباره شون توضیح میدین؟
کد:
namespace MyClasses
{
public class Comparable : IComparable, IName
{
public string Name { get; set; } // اینترفیس IName بخاطر این پیاده سازی شد که در جنریک ها _کلاس Sortable<Type> _ شی ای از نوع جنریک _ مثلا شی this[0] در همون کلاس_ قابلیت تبدیل به کلاس ها رو ندارن و جنریک ها فقط میتونن به اینترفیس ها تبدیل بشن و بخاطر همین اگه خواستیم به پروپرتی Name از طریق شی جنریک ها دسترسی پیدا کنیم ، مشکلی نداشته باشیم
public Comparable(string name)
{
this.Name = name;
}
public int CompareTo(object obj)
{
Comparable destinationStr = obj as Comparable;
if (destinationStr != null)
{
return this.Name.CompareTo(destinationStr.Name);
}
return 0;
}
}
public class Sortable<Type>
{
private Type[] TypeInstance;
private int CurrentIndex;
private int Length;
public Type this[int index]
{
get
{
if (index < this.TypeInstance.Length)
{
this.CurrentIndex = index;
return this.TypeInstance[index];
}
return default(Type);
}
set
{
if (index < this.TypeInstance.Length)
{
//this.index = index;
this.TypeInstance[index] = value;
}
}
}
public Sortable(int length)
{
this.CurrentIndex = -1;
this.Length = length;
this.TypeInstance = new Type[length];
}
public void Sort()
{
if (this[0] is IComparable)
{
for (int curIndex = 0; curIndex < this.Length; curIndex++)
{
IComparable iComp = this[curIndex] as IComparable; // شی از نوع MyClasses.Comparable بهش داده میشه یعنی this[curIndex] از نوع MyClasses.Comparable پس شی iComp هم شی MyClasses.Comparable هست
if (iComp != null)
{
for (int allIndex = 0; allIndex < this.Length; allIndex++)
{
if (allIndex > curIndex) // اگر عضو مقایسه شونده از مقایسه کننده بزرگتر بود ، چون اگه کوچکتر باشه یعنی در حلقه ای که دفعات قبل تکرار شد ، مقایسه شد و اگه مساوی باشه که یعنی خودش رو با خودش میخواد مقایسه کنه
{
int sortedNumber = iComp.CompareTo(this[allIndex]); // پس متد CompareTo از کلاس MyClasses.Comparable رو اجرا میکنه چون متغییر iComp شی ای از کلاس MyClasses.Comparable رو داره
if (sortedNumber > 0) // اگر شی iComp بزرگتر از شی this[allIndex] هست ، پس یعنی باید جاشون عوض شه
{
// الگوریتم جابجایی و ترتیب ایندکسر همین کلاس
Type temp = this[allIndex];
this[allIndex] = this[curIndex];
this[curIndex] = temp;
this.Sort(); // دوباره این متد رو اجرا کن (متد بازگشتی) تا از اول برای مرتب بودن چک کنه تا شامل اعضایی که تازه جابجا شدن هم بشن
return; // متدهای قبلی ای که در سلسله مراتب توابع بازگشتی اجرا شدن ، دیگه لازم نیست ادامه شون رو اجرا کنن چون آخرین متد بازگشتی ، همه چیز رو چک کرده و اگه همه ی اعضا مرتب باشن ، تموم میشه
}
}
}
}
}
}
}
}
public interface IName
{
string Name { get; set; }
}
}
و در رویدادی در فرم :
کد:
private void btnInterface6_Click(object sender, EventArgs e)
{
Page2Class.Sortable<Page2Class.Comparable> first = new Page2Class.Sortable<Page2Class.Comparable>(3);
first[0] = new Page2Class.Comparable("ahmad");
first[1] = new Page2Class.Comparable("saber");
first[2] = new Page2Class.Comparable("mohammad!");
Page2Class.Sortable<Page2Class.Comparable> secand = new Page2Class.Sortable<Page2Class.Comparable>(3);
secand[0] = new Page2Class.Comparable("akbar 3");
secand[1] = new Page2Class.Comparable("mahmood");
secand[2] = new Page2Class.Comparable("ali");
first.Sort();
secand.Sort();
for (int i = 0; i < 3; i++)
{
MessageBox.Show(first[i].Name);
}
for (int i = 0; i < 3; i++)
{
MessageBox.Show(secand[i].Name);
}
}
پس میشه گفت یکی از کاربرد اینترفیس ها ، توی جنریک هاست . درسته؟
بلهچیزی لازم نیست از کاربر دریافت کنه، شما یه مجموعه داخل List دارید که باید مرتب بشه، از هر الگوریتم مرتب سازی ای هم استفاده کنه یه مقایسه داره بین a و b که هر دو اعضاء ای از همون لیست هستند،
با a.CompareTo(b) مقایسه انجام میشه دیگه. چه چیزی لازم داره که در اختیار نداشته باشه؟ مجموعه رو و متد مقایسه رو لازم داره که هر دو رو هم داره.
چه ربطی داره. T یک نوع داده نامشخص برای List که الزاما هم Sort شدنی نیست. یعنی ممکنه از قابلیت Sort اصلا استفاده نشه. اصلا الزامی وجود نداره که T اینترفیس خاصی رو پیاده سازی کرده باشه.
چیزی که گفتم ، غلط بود یعنی در بدنه متد Sort ، پیش فرضش این نیست که در کلاس نوع جنریک (مثلا در کلاس Dog) ، اینترفیسی رو پیاده سازی کرده باشه
دوم اینکه طبق نکته ی بالا ، شی جنریک ها اصلا نمیتونن به کلاس تبدیل بشن
ممنوندلیل چی؟ اگه مرتب کردن بر اساس مقایسه گر پیشفرض خود شیء باشه، یعنی کد نویس نخواد از مقایسه و مرتب سازی اختصاصی ای استفاده کنه که پارامتر وارد نمیشه و حالا اگه اون نوع داده مورد نظر مقایسه گر اختصاصی شیء با شیء داشته در اولویت ئه و اگه نباشه از object vs object استفاده می کنه (سربار داره چون کند تر ئه) و اگه اونم نباشه خطا میده. ولی اگه برای مرتب کردن متد و روش خاصی مد نظر کد نویس باشه باید مشخص اش کنه. فرضا بخواد int ها رو نزولی مرتب کنه.
والا من قاتی کردماون همه در موردشون صحبت کردیم، بازم آخرش حرف اشتباه اولیه خودتون رو می زنید. حافظه شیء در هر صورت توسط GC مدیریت میشه و ربطی به IDisposable و Dispose هم نداره. چه پیاده سازی شون بکنید و چه نکنید مسئول حافظه شیء GC ئه و وقتی دیگه بهش دسترسی وجود نداشت و با تاخیر GC حافظه شو آزاد می کنه. این مساله هیچ ربطی به Dispose نداره. حافظه این همه کلاس و شیء که Disposable رو پیاده سازی نکرده اند رو کی آزاد می کنه؟ هر چند بار هم Dispose رو اجرا کنید شیء به خودی خود سر جاشه و حافظه اش هم همینطور. Dispose هیچ موقع حافظه خود شیء رو نمیتونه آزاد کنه، خودش متدی از شیء ئه. در این مورد قبلا خیلی صحبت کردیم. اون Heap رو هم من نگفتم، بهتره جایی هم عنوانش نکنید چون هیچ تضمینی وجود نداره که Heap باشه. من نه تاییدش می کنم و نه ذکر کردنش رو توصیه می کنم. اگه شما طراح GC بودید و پیاده سازیش با شما بوده، حرفی نیست، وگرنه دلیلی نداره در مورد موضوعی صحبت بشه که نه معتبر ئه و نه برای کد نویس زبان #C اطلاعاتش مفید و موثر ئه. اینکه حافظه GC از نظر داخلی از چه ساختاری ئه مثل اینه که بخواهید در داروخانه فرمول شیمیایی دارو رو برای بیمار تشریح کنید، چیزی رو بگید که مفید باشه و بدرد بخوره. حالا اطلاعات اشتباه باشه یا نباشه بماند.
توی یه جا میبینیم ، برای متد Dispos ، کدی میدن (سایت استک اورفلو و مایکروسافت) که شی Managed رو رها میکنه . برای قسمت کدهای Unmanaged هم میدن . بعد توی توضیحاتش یکی میگه برای Managed کار نمیکنه و برای Unmagaed کار میکنه . یکی دیگه ، یه چیز دیگه میگه
اصلا متد Dispos رو ولش کنیم
حافظه ی Heap که دیگه اسنادش تو مایکروسافت فکر کنم باشه . خیلی جاهام درباره اش بحث کردن
منظورم مثلا 20 تا از مهمترین و کاربردی ترین اینترفیس هانهر چی I توی Framework ئه مهم ئه، اگه مهم و پر استفاده نبود که داخل Framework نمیذاشتن. کلا ماهیت Framework با کتابخانه های دیگه فرق اش در همینه که چیزهایی که وجودشون ضروری ئه یا پر استفاده و مرسوم ئه داخلش قرار میگیره. اینکه کدوم بیشتر استفاده میشه به موضوع پروژه و البته تسلط برنامه نویس بستگی داره. هر چقدر برنامه نویس به امکانات موجود بیشتر مسلط باشه و بشناستشون بیشتر ازشون استفاده می کنه.
اون اینترفیس هایی که نوشتم نمیدونم درباره ی چه قضیه ای هستن ، درباره شون توضیح میدین؟
آخرین ویرایش: