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

时间:2017-03-16 21:18:35

标签: 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.
  • 第一个分配失败,因为编译器认为alNone是我声明的那个而不是TAlign中定义的Controls.pas成员。
  • 第二个失败是因为Controls表示该名称的TForm属性。

我意识到有很多方法可以解决这个问题(将alNone成员重命名为最简单的),但我很好奇是否有办法在另一个单位中对某个属性进行资格认定。 单元名称与当前作用域中的标识符冲突。

2 个答案:

答案 0 :(得分:10)

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

TAlign.alNone

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

答案 1 :(得分:6)

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

someAlign  := TAlign.alNone;
someMyType := TMyType.alNone;

这种枚举的使用被称为" scoped enums"并且在旧版本的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

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

在这些情况下,只需定义一个新的常量来创建一个明确的"本地别名"对于另一个单元中的常量,并在单元名称明确无误的情况下引入它。类似于:

  type
    TMyResult = (
      mrOk,
      mrFailed) ;

  const
    Controls_mrOk = Controls.mrOk;  // mrOk is a const, not an enum member