不完全确定这个问题措辞是否恰当,但我之前曾问过这个与此问题有关的问题:How do I correctly implement a Set in a class as a property?
我喜欢将代码保持为尽可能短,最小和可读,这是我认为某些代码可以写得更好但我遇到问题的地方。
首先读取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;
更干净,更短,更好的方式:
CheckListBox1.Checked[0] := (Delphi1 in IDECompatibility);
CheckListBox1.Checked[1] := (Delphi2 in IDECompatibility);
CheckListBox1.Checked[2] := (Delphi3 in IDECompatibility);
现在我想用另一种方式来设置值。
目前,我所知道的唯一方法就是漫长的道路:
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];
如果可能,我想做这样的事情:
IDECompatibility[Delphi1] := CheckListBox1.Checked[0]; // Array type required
IDECompatibility[Delphi2] := CheckListBox1.Checked[1]; // Array type required
IDECompatibility[Delphi3] := CheckListBox1.Checked[2]; // Array type required
有Exclude
和Include
成员,但我不确定这里是否需要这些成员。
所以,如上所述 - 是否有更简单的方法来根据布尔值定义枚举类型?
谢谢。
答案 0 :(得分:5)
我知道你提到了XE,但是有人看到这个问题可能会对这个答案感兴趣,以获得更新的版本。
在XE6中,这可以通过设置帮助程序(几乎)完成:
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;
由于不允许将Element设为默认数组属性,因此必须指定属性名称。
var
MySet: TMySet;
begin
MySet.Element[0] := False;
MySet.Element[1] := not MySet.Element[0];
end;
答案 1 :(得分:5)
不,目前Delphi中没有可用于set
类型的数组访问。我建议创建一个辅助索引属性,它可以模仿像访问一样的数组,并且会隐藏包含或排除集合中元素所需的代码。
从我到目前为止看到的情况来看,人们通常会为Is
或Has
前缀具有基本访问权限的属性添加前缀。在您的情况下,我会遵循此规则并创建一个名为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;
一个示例用法:
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;
答案 2 :(得分:0)
基于Uwes解决方案,我创建了这个帮助器(需要XE6),可以用于变量和属性:
TGridOptionsHelper = record helper for TGridOptions
public
/// <summary>Sets a set element based on a Boolean value</summary>
/// <example>
/// with MyGrid do Options:= Options.SetOption(goEditing, False);
/// MyVariable.SetOption(goEditing, True);
/// </example>
function SetOption(GridOption: TGridOption; const Value: Boolean): TGridOptions;
end;
function TGridOptionsHelper.SetOption(
GridOption: TGridOption; const Value: Boolean): TGridOptions;
begin
if Value then Include(Self, GridOption) else Exclude(Self, GridOption);
Result:= Self;
end;
备注:与Uwes解决方案相比,我还省略了用于读取set元素的代码 - 应该使用in
运算符来完成。