Delphi - 当单元名称与属性名称相同时,如何解决冲突?

ros*_*mcm 10 delphi scope delphi-2007

下面的简单示例是我试图解决冲突的问题的缩写,其中我有一个与VCL成员同名的枚举类型成员.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

type
    TSomeType = (
      alNone,
      alSome,
      alMany) ;

procedure TForm1.FormCreate(Sender: TObject);
begin
Self.Align := alNone ;                    // 1.  type mismatch
Self.Align := Controls.alNone ;           // 2.  "Controls" is also a property of TForm
end ;

end.
Run Code Online (Sandbox Code Playgroud)
  • 第一个赋值失败,因为编译器认为alNone是我声明的那个而不是在其中TAlign定义的成员Controls.pas.
  • 第二个失败是因为它Controls意味着该TForm名称的属性.

我意识到有很多方法(重命名alNone成员是最简单的),但我很好奇是否有一种方法来限定对另一个单元中属性的引用,其中单元名称与当前作用域中的标识符冲突.

Dav*_*nan 10

使用类型名称对其进行限定:

TAlign.alNone
Run Code Online (Sandbox Code Playgroud)

我没有意识到我写这篇文章时编译器版本是相关的.此语法仅在Delphi 2010或XE中可用.那里的答案不适合标记版本Delphi 2007. Deltics的答案涵盖了更多细节.


Del*_*ics 6

正如David的回答所示,对于枚举类型或其他情况,可以使用类型来限定所涉及的标识符,那么您当然可以根据需要使用类型名称:

someAlign  := TAlign.alNone;
someMyType := TMyType.alNone;
Run Code Online (Sandbox Code Playgroud)

枚举的这种使用被称为" 范围枚举 ",并且在旧版本的Delphi编译器中不受支持.我相信XE2可能是它被引入的时候.当然,这是默认情况下以这种方式强制确定范围的版本.

虽然它可以通过编译器指令关闭.关闭时,您仍然可以使用范围内的枚举,但您不需要.

在支持此功能的版本中,您必须限定在打开时定义的任何枚举.使用在关闭时定义的枚举时,您可以选择是否质量.

type
{$SCOPEDENUMS ON}
TFoo = (Black, White);  // MUST qualify:  eg. "TFoo.Black"

{$SCOPEDENUMS OFF}
TBar = (Black, White);  // MAY qualify or not if/as needed
Run Code Online (Sandbox Code Playgroud)

对于没有作用域枚举支持的旧版本Delphi,或者在标识符不是枚举成员且无法通过类型限定的情况下 - 例如,如果您的标识符与某个单元级别标识符冲突(例如mrOk,在控件中),则你需要多做一点工作,但不多.

在这些情况下,只需定义一个新常量,为另一个单元中的常量创建一个明确的"本地别名",并在单位名称明确的地方引入它.相近:

  type
    TMyResult = (
      mrOk,
      mrFailed) ;

  const
    Controls_mrOk = Controls.mrOk;  // mrOk is a const, not an enum member
Run Code Online (Sandbox Code Playgroud)