有没有更简单的方法来定义基于布尔值的枚举类型?

6 delphi delphi-xe

概观

不完全确定这个问题的措辞是否恰当,但我之前曾问过这个与此问题有关的问题:我如何在一个类中正确地实现一个Set作为一个属性?

我喜欢尽可能地将代码保持为短,最小和可读,这是我认为某些代码可以写得更好但我遇到问题的地方.


首先,有两种方法可以读取Set中的值:

漫长的道路:

if (Delphi1 in IDECompatibility) then
  CheckListBox1.Checked[0] := True;
if (Delphi2 in IDECompatibility) then
  CheckListBox1.Checked[1] := True;
if (Delphi3 in IDECompatibility) then
  CheckListBox1.Checked[2] := True;
Run Code Online (Sandbox Code Playgroud)

更清洁,更短,更好的方式:

CheckListBox1.Checked[0] := (Delphi1 in IDECompatibility);
CheckListBox1.Checked[1] := (Delphi2 in IDECompatibility);
CheckListBox1.Checked[2] := (Delphi3 in IDECompatibility);
Run Code Online (Sandbox Code Playgroud)

现在我想用另一种方式来设置值.

目前,我所知道的唯一方法是漫长的道路:

if CheckListBox1.Checked[0] then
  IDECompatibility := IDECompatibility + [Delphi1]
else
  IDECompatibility := IDECompatibility - [Delphi1];

if CheckListBox1.Checked[1] then
  IDECompatibility := IDECompatibility + [Delphi2]
else
  IDECompatibility := IDECompatibility - [Delphi2];

if CheckListBox1.Checked[2] then
  IDECompatibility := IDECompatibility + [Delphi3]
else
  IDECompatibility := IDECompatibility - [Delphi3];
Run Code Online (Sandbox Code Playgroud)

如果可能的话,我想做这样的事情:

IDECompatibility[Delphi1] := CheckListBox1.Checked[0]; // Array type required
IDECompatibility[Delphi2] := CheckListBox1.Checked[1]; // Array type required
IDECompatibility[Delphi3] := CheckListBox1.Checked[2]; // Array type required
Run Code Online (Sandbox Code Playgroud)

有成员ExcludeInclude成员,但我不确定这里是否需要这些.

因此,如上所述 - 是否有更简单的方法来定义基于布尔值的枚举类型?

谢谢.

Uwe*_*abe 5

我知道你提到了XE,但是对于这个问题,有人可能会对这个答案感兴趣.

在XE6中,这可以通过set helper完成(几乎):

type
  TMyRange = 0..7;
  TMySet = set of TMyRange;

type
  TMySetHelper = record helper for TMySet
  public
    function GetElement(Index: TMyRange): Boolean;
    procedure SetElement(Index: TMyRange; const Value: Boolean);
    property Element[Index: TMyRange]: Boolean read GetElement write SetElement;
  end;
Run Code Online (Sandbox Code Playgroud)

由于不允许将Element设为默认数组属性,因此必须指定属性名称.

var
  MySet: TMySet;
begin
  MySet.Element[0] := False;
  MySet.Element[1] := not MySet.Element[0];
end;
Run Code Online (Sandbox Code Playgroud)


TLa*_*ama 5

不,目前setDelphi中没有可用于类型访问的数组.我建议创建一个辅助索引属性,它可以模仿像访问一样的数组,并且会隐藏包含或排除集合中元素所需的代码.

从我到目前为止看到的情况来看,人们通常会对具有一些基本访问权限IsHas前缀的属性进行前缀.在你的情况下,我会遵循这个规则并建立一个叫做的财产HasIDECompatibility或让我们说IsIDECompatible.此属性将是Boolean类型并且将具有getter,通过该getter可以返回元素是否在内部set字段内的信息.在setter中,它将根据输入值将元素包含或排除到集合中.

在更通用的代码中,它将是:

type
  TElement = (
    Element1,
    Element2,
    Element3
  );
  TElements = set of TElement;

  TMyClass = class
  private
    FElements: TElements;
    function GetElement(Kind: TElement): Boolean;
    procedure SetElement(Kind: TElement; Value: Boolean);
  public
    // this property is for direct access to the set field; if your class would
    // be a TComponent descendant and you'd publish this property, you'd see it
    // in the Object Inspector represented by a set of check boxes
    property Elements: TElements read FElements write FElements;
    // this property is just a helper for array like access to the internal set
    // field
    property HasElement[Kind: TElement]: Boolean read GetElement write SetElement;
  end;

implementation

{ TMyClass }

function TMyClass.GetElement(Kind: TElement): Boolean;
begin
  Result := Kind in FElements;
end;

procedure TMyClass.SetElement(Kind: TElement; Value: Boolean);
begin
  if Value then
    Include(FElements, Kind)
  else
    Exclude(FElements, Kind);
end;
Run Code Online (Sandbox Code Playgroud)

并举例说明:

procedure TForm1.Button1Click(Sender: TObject);
var
  MyClass: TMyClass;
begin
  MyClass := TMyClass.Create;
  try
    // write elementary property value
    MyClass.HasElement[Element1] := CheckBox1.Checked;
    MyClass.HasElement[Element2] := CheckBox2.Checked;
    // read elementary property value
    CheckBox3.Checked := MyClass.HasElement[Element1];
    CheckBox4.Checked := MyClass.HasElement[Element2];

    // or you can access MyClass.Elements set at once as you were used to do
    // which gives you two ways to include or exclude elements to the set
  finally
    MyClass.Free;
  end;
end;
Run Code Online (Sandbox Code Playgroud)