Delphi 关于Default函数

Default 是 Delphi 的一个内建函数/关键字,用于获取任何类型的默认值(零值)。

使用 Default 的优点:

  • 更清晰表达"清零"的意图

  • 即使将来记录增加字段,也不需要修改

  • 代码更简洁

// Default() 返回指定类型的"零值"或"空值"
var
    I: Integer;
    S: string;
    R: TDeptSupplierInfo;
begin
    I := Default(Integer);  // 0
    S := Default(string);   // ''(空字符串)
    R := Default(TDeptSupplierInfo);  // 所有字段归零
end;

它的调用方式主要有三种:

//方式一:显式指定类型
    Value := Default(Integer);  // 指定类型参数

//方式二:类型推断(Delphi 10.3 Rio 及更高版本)
    Value := Default;  // 编译器根据 Value 的类型自动推断

//方式三:泛型中使用
function GetDefaultFor<T>: T;
begin
    Result := Default(T);  // 返回类型 T 的默认值
end;

各类类型的默认值

// 数值类型 → 0
var
    IntVal: Integer := Default(Integer);        // 0
    FloatVal: Double := Default(Double);        // 0.0
    CurrVal: Currency := Default(Currency);     // 0

// 字符串类型 → ''(空字符串)
var
    StrVal: string := Default(string);          // ''
    AnsiVal: AnsiString := Default(AnsiString); // ''

// 布尔类型 → False
var
    BoolVal: Boolean := Default(Boolean);       // False

// 枚举类型 → 第一个枚举值(通常是0)
type
    TColor = (Red, Green, Blue);
var
    ColorVal: TColor := Default(TColor);        // Red(枚举的第一个值)

// 字符类型 → #0
var
    CharVal: Char := Default(Char);             // #0

// 指针类型 → nil
var
    Ptr: Pointer := Default(Pointer);           // nil
    Obj: TObject := Default(TObject);           // nil

// 接口类型 → nil
var
    Intf: IInterface := Default(IInterface);    // nil

// 动态数组 → nil
var
    Arr: TArray<Integer> := Default(TArray<Integer>);  // nil(长度为0)

// 记录类型 → 所有字段归零
type
    TMyRecord = record
        ID: Integer;
        Name: string;
        Price: Double;
    end;
var
    Rec: TMyRecord := Default(TMyRecord);
    // Rec.ID = 0
    // Rec.Name = ''
    // Rec.Price = 0.0

// 静态数组 → 所有元素归零
var
    Arr: array[0..4] of Integer := Default;  // 所有元素为 0

// Variant → Unassigned
var
    V: Variant := Default(Variant);              // Unassigned

 

使用场景一:确保记录完全初始化

function GetDeptAndSupplierID(const ATag: Integer): TDeptSupplierInfo;
begin
    Result := Default(TDeptSupplierInfo);  // 先清零
    
    if (ATag mod 10) = 0 then
        Result.DeptID := ATag div 10
    else
        Result.SupplierID := (ATag - 1) div 10;
    // 不用再显式赋值另一个字段为 0 了
end;

// 对比原来的代码:
function GetDeptAndSupplierID(const ATag: Integer): TDeptSupplierInfo;
begin
    // 没有使用 Default,需要手动确保所有字段都有值
    if (ATag mod 10) = 0 then
    begin
        Result.DeptID := ATag div 10;
        Result.SupplierID := 0;        // 必须显式赋值
    end
    else
    begin
        Result.DeptID := 0;            // 必须显式赋值
        Result.SupplierID := (ATag - 1) div 10;
    end;
end;

 

使用场景二:重置变量

procedure ResetForm;
var
    Info: TDeptSupplierInfo;
begin
    Info.DeptID := 10;
    Info.SupplierID := 20;
    
    // 使用过程中...
    
    // 需要重置
    Info := Default(TDeptSupplierInfo);  // 变回 (0, 0)
end;

 

使用场景三:函数返回默认值

function FindSupplier(const ID: Integer): TDeptSupplierInfo;
begin
    // 查找逻辑...
    
    if not Found then
        Result := Default(TDeptSupplierInfo)  // 返回 (0, 0)
    else
    begin
        Result.DeptID := ...;
        Result.SupplierID := ...;
    end;
end;

 

使用场景四:参数默认值

procedure ProcessData(const Info: TDeptSupplierInfo = Default(TDeptSupplierInfo));
begin
    if Info.IsValid then
        // 处理有效数据
    else
        // Info 是 (0, 0),表示无效
end;

 

 Default() 的底层实现

// Default() 实际上是一个编译器内建函数
// 等价于:
procedure FillChar(var X; Count: NativeInt; Value: Byte);

// 对于记录类型,Default 相当于:
var
    Info: TDeptSupplierInfo;
begin
    FillChar(Info, SizeOf(TDeptSupplierInfo), 0);
    // 这会将整个记录的内存区域全部填充为 0
end;

 

 注意事项

type
    TMyRecord = record
        Name: string;     // string 是托管类型
        Count: Integer;   // Integer 是值类型
    end;

// 注意:Default() 会将 string 设置为 ''(空字符串)
// 这不是 nil,而是一个有效的空字符串
var
    Rec: TMyRecord;
begin
    Rec := Default(TMyRecord);
    // Rec.Name 是 ''(一个有效的空字符串对象)
    // Rec.Count 是 0
    
    // 可以安全地使用:
    if Rec.Name = '' then  //  安全,不是 nil
        ShowMessage('Empty');
end;

 

 

posted @ 2026-05-04 14:49  一曲轻扬  阅读(72)  评论(0)    收藏  举报