Delphi的Property能否在无法更新变量时返回布尔值?
Delphi 属性赋值失败返回状态的实现方案
Delphi 原生的属性语法不支持赋值操作直接返回布尔值,因为 property 的 write 修饰符绑定的 setter 方法必须是无返回值的 procedure,无法直接通过 对象.属性 := 新值 这类赋值语法拿到赋值结果。可以用以下三种常用方案实现需求:
方案1:使用带返回值的独立赋值方法(最推荐)
直接放弃通过属性赋值的写法,新增公开的带返回值的赋值方法,属性仅保留读权限,避免外部误操作。
实现代码示例:
TPlayer = class(TObject) strict private FUsername : String; private function GetUsername() : String; public // 返回值为True表示赋值成功,False表示校验不通过未赋值 function TrySetUsername(const AUsername: String): Boolean; // 用户名属性仅开放读权限 property Username : String read GetUsername; end; function TPlayer.TrySetUsername(const AUsername: String): Boolean; begin // 先校验格式 Result := Length(AUsername) > 3; if Result then FUsername := AUsername; end; function TPlayer.GetUsername() : String; begin Result := FUsername; end;
调用方式:
var LPlayer: TPlayer; begin LPlayer := TPlayer.Create; try if not LPlayer.TrySetUsername('abc') then ShowMessage('用户名长度必须大于3位,赋值失败'); finally LPlayer.Free; end; end;
该方案逻辑清晰,不会出现状态混淆,是 Delphi 开发中这类需求的主流实现方式。
方案2:新增上次赋值状态属性(需保留属性写权限时使用)
如果必须保留属性的写权限,可以额外新增一个只读属性记录上一次属性赋值的结果。
实现代码示例:
TPlayer = class(TObject) strict private FUsername : String; FLastSetSuccess: Boolean; private procedure SetUsername(const AUsername : String); function GetUsername() : String; public property Username : String read GetUsername write SetUsername; // 只读属性,返回上一次用户名赋值是否成功 property LastSetSuccess: Boolean read FLastSetSuccess; end; procedure TPlayer.SetUsername(const AUsername : String); begin FLastSetSuccess := Length(AUsername) > 3; if FLastSetSuccess then FUsername := AUsername; end; function TPlayer.GetUsername() : String; begin Result := FUsername; end;
调用方式:
LPlayer.Username := 'abc'; if not LPlayer.LastSetSuccess then ShowMessage('用户名长度不符合要求,赋值失败');
该方案的缺点是:连续多次赋值时,上一次的状态会被最新的赋值操作覆盖,不适合多线程或者批量赋值的场景。
方案3:校验失败抛出异常(适合非法输入为异常场景时使用)
如果非法输入属于非正常业务流程的异常情况,可以在校验不通过时直接抛出异常,由调用方捕获处理。这也是 Delphi VCL/FMX 框架内置属性常用的校验方式。
实现代码示例:
procedure TPlayer.SetUsername(const AUsername : String); begin if Length(AUsername) <= 3 then raise EArgumentException.Create('用户名长度必须大于3位'); FUsername := AUsername; end;
调用方式:
try LPlayer.Username := 'abc'; except on E: EArgumentException do ShowMessage(E.Message); end;
内容的提问来源于stack exchange,提问作者Maik Hasler
相关产品推荐
相关产品推荐

