PDA

View Full Version : سوال: آیا می تونیم بدون برنامه نویسی بفهمیم یک شیی وجود داره یا نه؟



kamran_14
پنج شنبه 19 اسفند 1389, 13:39 عصر
سلام
آیا می تونیم بدون برنامه نویسی بفهمیم یک شیی وجود داره یا نه؟
مثلا تعدادی آرایه کنترلی را هنگام اجرا ایجاد کردیم
و بعد چند تا از این آرایه ی کنترلی را توسط دستور Destory حذف کردیم
و بعد
می خوام باز شی های باقیمانده را حذف کنم
اما من چون حتی شی هایی را که حذف شده اند را بررسی می کنم خطا می ده
آیا دستوری وجود داره که بدونم آن شی وجود داره یا نه، بعد حذف کنم
الگوریتمی که من برای وجود یا عدم وجود شی آرایه ی کنترلی در نظر گرفتم خیلی حافظه اشغال می کنه .
من به این خاطر می خوام برنامه نویسی نباشه.
یا اگه یه الگوریتمی که حافظه ی کمتری مصرف کنه می دونید اگه امکان داره راهنمایی کنید؟

Delphi 2010
پنج شنبه 19 اسفند 1389, 14:09 عصر
از تابع FindComponent استفاده کن برای پیدا کردن بقیه کنترل هایی که حذف نشده اند

kamran_14
پنج شنبه 19 اسفند 1389, 15:18 عصر
از تابع FindComponent استفاده کن برای پیدا کردن بقیه کنترل هایی که حذف نشده اند
سلام
ببخشید من این کد و نوشتم ولی در نبود شی دوباره error داد

tcomponent(FindComponent('button1')).Destroy;
می شه اگه این کد اشتباه بود تصحیح کنید؟

MohsenB
پنج شنبه 19 اسفند 1389, 16:21 عصر
سلام

برا ساخت آرایه ای از اشیاء از کد زیر استفاده کن :


var
btnMyBtn : array[1..10] of TBitBtn;


تو این کد توجه کنید که بعلت اینکه ممکنه اشیائی از همین نوع رو فرم باشه یه اسم مناسب بجای btn اول اسم اشیاء قرار بدید تا بشه فقط دنبال همون اشیاء گشت .

بعد از اون برای حذف اونایی که باقی موندن از کد زیر استفاده کنید :


for tmpi := 0 to ControlCount-1 do
if copy(Controls[tmpi].Name,1,3)='btn' then
(Controls[tmpi] as TBitBtn).Free;


یه نکته مهم : برای حذف یک شیء از Free استفاده کنید .

Felony
جمعه 20 اسفند 1389, 06:08 صبح
برای اینکه با خطا مواجه نشید ابتدا باید جک کنید که شئ وجود داره یا نه بعد آزادش کنید ، برای این کار یا باید از تابع Assigned استفاده کنید یا اگر اسم کنترل رو به صورت رشته ای دارین و میخواین با همون بررسی رو انجام بدید به صورت زیر :
if FindComponent('Button1') <> nil then
// Free component here

MohsenB
جمعه 20 اسفند 1389, 08:49 صبح
سلام

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


for tmpi := 0 to 10 do
if btnMyBtn[tmpi] <> nil then
btnMyBtn[tmpi].Free;

SAASTN
جمعه 20 اسفند 1389, 11:51 صبح
این کد خیلی کار خاصی انجام نمی ده:
if btnMyBtn[tmpi] <> nil then
btnMyBtn[tmpi].Free;

چون اگه خود Free رو بررسی کنید می بینید که همین مقایسه درش انجام شده و شما عملا همون مقایسه رو یکبار دیگه تکرار کردید:
procedure TObject.Free;
begin
if Self <> nil then
Destroy;
end;


اما یه نکته کوچیک هستش که نمی دونم به مسئله دوستمون ربطی داره یا نه و اونم اینه که نمونه ها بعد از آزاد سازی nil نمی شن و شما خودتون باید اونها رو دوباره nil کنید. یعنی توی کد زیر توی خط 6م خطا داریم:
var
anObject: TObject;
begin
anObject := TObject.Create;
anObject.Free;
anObject.Free;
end;

درصورتی که اگه همین کد رو به شکل زیر بنویسیم دیگه خطا نخواهیم داشت:
var
anObject: TObject;
begin
anObject := TObject.Create;
anObject.Free;
anObject := nil;
anObject.Free;
end;

یا به جای Free و سپس nil کردن می تونید از دستور FreeAndNil استفاده کنید.
یه نکته دیگه هم هست که بازم نمی دونم مربوطه یا نه ولی حسم میگه هست. به نظر میاد توی کار شما طول عمر عناصر آرایه یکسان نیست یعنی کنترل ها به مرور آزادسازی می شن. خوب اگه این فرض درست باشه اصلا استفاده از آرایه کار درستی نیست. حتی اگر فرض بگیریم که شما از آرایه داینامیک هم استفاده کنید و بعد از آزادسازی هر کنترل، اون رو با آخرین عنصر آرایه Swap کنید و طول آرایه رو یکی کاهش بدید باز هم خیلی کار قشنگی نسیت. برای همچین وضعیتهایی بنا به نوع کاربرد کلاسهایی مثل TList یا TCollection تعریف شدند. برای نمونه:
const
ObjectsCount = 32;
var
anObject: TObject;
aList: TList;
I: Integer;
begin
aList := TList.Create;
// initialize anObject
for I := 0 to ObjectsCount - 1 do
begin
anObject := TObject.Create;
aList.Add(anObject)
end;

// ...

I := 0;
while I < aList.Count do
if Condition then
begin
anObject := TList[I];
// finalize anObject
FreeAndNil(anObject);
aList.Delete(I); // یا مثلا aList.Remove(Form1.FindComponent('Button1')); !چشمک!
end
else
Inc(I);
end;

Felony
جمعه 20 اسفند 1389, 20:03 عصر
چون اگه خود Free رو بررسی کنید می بینید که همین مقایسه درش انجام شده و شما عملا همون مقایسه رو یکبار دیگه تکرار کردید:
ایشون متد Destroy کامپوننت رو برای آزاد سازی صدا زده و راهی که من گفتم برای حل اون مشکل بود ، چیزی که شما گفتی مربوط میشه به متد Free .


اما یه نکته کوچیک هستش که نمی دونم به مسئله دوستمون ربطی داره یا نه و اونم اینه که نمونه ها بعد از آزاد سازی nil نمی شن و شما خودتون باید اونها رو دوباره nil کنید. یعنی توی کد زیر توی خط 6م خطا داریم:
در اون مورد دلفی تابع FreeAnd Nil رو در اختیارتون میزاره که هم شئ رو آزاد میکنه و هم nil .