直接上例子了,基础知识自己去了解,首先定义一个类:
TPerson = class
public
name: string;
age: Integer;
constructor Create(name: string; age: Integer);
end;
constructor TPerson.Create(name: string; age: Integer);
begin
Self.name := name;
Self.age := age;
end;
例子1,首先了解Free,仅仅是销毁堆中数据,栈中变量的值依然是堆中的地址:
procedure TForm3.btn1Click(Sender: TObject);
var
ps: TPerson;
begin
ps := TPerson.Create('小李', 10);
ps.Free; //这里调用Free,堆中的数据已经被释放,但是ps这个指针的值还是堆中对象的地址
if Assigned(ps) then //Assigned方法,当ps指针的值为nil的时候,才返回False,由于ps的值不为nil,这里显然会返回True
begin
mmo1.Lines.Add('yes');
mmo1.Lines.Add(ps.name); //这里产生了Av错误,原因是ps堆中的对象已经被释放
end else begin
mmo1.Lines.Add('no');
end;
end;


例子2,知道即使你不创建实例,Assigned依然是true;
procedure TForm3.btn3Click(Sender: TObject);
var
p: TPerson;
begin
//p不初始化,会自由随机分配一个地址和值,值也是原来的自由值,不一定是nil,通常都不是nil
if Assigned(p) then
begin
//只要p指针的值不是nil,这里就会返回true,所以是yes
mmo1.Lines.Add('yes');
end else begin
mmo1.Lines.Add('no');
end;
end;


例子3:对例子1进行改造,使用FreeAndNil,将堆中数据释放,同时将栈中指针的值变为nil;
procedure TForm3.btn3Click(Sender: TObject);
var
ps: TPerson;
begin
ps := TPerson.Create('小李', 10);
FreeAndNil(ps); //指针的值也变成nil了
if Assigned(ps) then
begin
mmo1.Lines.Add('yes');
end else begin
mmo1.Lines.Add('no'); //此时就自然到这里了
end;
end;



例子4,最后一个例子,得出官方的Assigned 不是我们需要的:
procedure TForm3.btn4Click(Sender: TObject);
var
ps, ps1: TPerson;
begin
ps := TPerson.Create('小李', 10);
ps1 := ps;
FreeAndNil(ps);
if Assigned(ps) then
begin
mmo1.Lines.Add('yes');
end else begin
mmo1.Lines.Add('no'); //ps指针的值是nil了,所以no
end;
if Assigned(ps1) then
begin
mmo1.Lines.Add('yes'); //ps1指针的值不是nil
//mmo1.Lines.Add(ps1.name); //这里就会报错,因为ps堆中的数据已经释放
end else begin
mmo1.Lines.Add('no');
end;
//显然上面不是我们要的结果,使用我们自己的函数
if AssignedEx(ps1, TPerson) then
begin
mmo1.Lines.Add('yes');
end else begin
mmo1.Lines.Add('no'); //由于ps1指向的堆中数据已经不存在,这里会no
end;
end;

好了综上得出官方的Assigned 有点简陋,不是我们需要的,引出我们的修改版:
/// <summary>
/// 判断实例释放释放
/// </summary>
/// <param name="AVar">实例变量</param>
/// <param name="className">实例类型</param>
function AssignedEx(AVar: TObject; AClass: TClass): Boolean;
begin
//首先判断变量指针的值是否为nil
if not Assigned(AVar) then
begin
Exit(False);
end;
//判断堆中的数据是否是当前类
try
//若AVar指向的堆中数据已释放,则这里调用.ClassName会AV异常
if AVar.ClassName = AClass.ClassName then
begin
Exit(True);
end else begin
Exit(False);
end;
except
//有异常说明堆中已经被释放掉了
Exit(False);
end;
end;