なので。ここでエレガンクルとはどういう意味ですか? 実装のエレガンス、使用のエレガンス、CPI の効率性、保守性 ? エレガンスはとても曖昧な言葉です...
のような流儀で使える型に変換するのが、使いやすくするための当然の方法だと思いますExtBoolean1 or (ExtBoolean2 and True)
。
ただし、必要な機能は、Delphi 2006 (それ自体はかなりバグのあるリリース) よりも前かそれより前のバージョンである可能性があるためDUnit
、多くのテストを行ってください..
使用する機能とその説明を一覧表示するには:
- 拡張レコード:クラスの代わりに Delphi で拡張レコード タイプを使用する必要があるのはいつですか? およびhttp://delphi.about.com/od/adptips2006/qt/newdelphirecord.htmおよびマニュアル
- 暗黙的な型キャストを含む操作のオーバーロード: 「拡張レコード」を通常の「データ型」変数に割り当てるときに、どの演算子をオーバーロードしますか? およびDelphiとマニュアルでの演算子のオーバーロード
- 関数のインライン化: Delphiとマニュアルでの inline キーワードの使用とは
これらのアイデアのいくつかを概説するには:
type
TExtBoolean = record
Value: (ebUnknown, ebTrue, ebFalse);
function IsNull: boolean; inline;
function Defined: boolean; inline;
class operator Implicit ( from: boolean ): TExtBoolean; inline;
class operator Implicit ( from: TExtBoolean ): boolean;
class operator LogicalAnd( Value1, Value2: TExtBoolean ): TExtBoolean;
class operator LogicalAnd( Value1: TExtBoolean; Value2: boolean): TExtBoolean; inline;
class operator LogicalAnd( Value1: boolean; Value2: TExtBoolean ): TExtBoolean;
....
end;
const Unknown: TExtBoolean = (Value: ebUnknown);
...
var v1: TExtBoolean;
v1 := False;
v1 := True;
v1 := Unknown;
...
class operator TExtBoolean.Implicit ( from: boolean ): TExtBoolean;
begin
if from
then Result.Value := ebTrue
else Result.Value := ebFalse
end;
class operator TExtBoolean.Implicit ( from: TExtBoolean ): Boolean;
begin
case from.Value of
ebTrue: Result := True;
ebFalse: Result := False;
else raise EConvertError.Create('....');
end;
function TExtBoolean.Defined: boolean;
begin
Result := (Self.Value = ebTrue) or (Self.Value = ebFalse);
end;
// this implementation detects values other than ebTrue/ebFalse/ebUnkonwn
// that might appear in reality due to non-initialized memory garbage
// since hardware type of Value is byte and may be equal to 3, 4, ...255
function TExtBoolean.IsNull: boolean;
begin
Result := not Self.Defined
end;
class operator TExtBoolean.And( Value1, Value2: TExtBoolean ): TExtBoolean;
begin
if Value1.IsNull or Value2.IsNull
then Result.Value := eb.Undefined
else Result := boolean(Value1) and boolean(Value2);
// Or, sacrificing readability and safety for the sake of speed
// and removing duplicate IsNull checks
// else Result := (Value1.Value = ebTrue) and (Value2.Value = ebTrue);
end;
class operator TExtBoolean.LogicalAnd( Value1, TExtBoolean; Value2: boolean): TExtBoolean;
begin
Result := Value2 and Value1;
end;
class operator TExtBoolean.LogicalAnd( Value1: boolean; Value2: TExtBoolean ): TExtBoolean;
begin
if Value2.IsNull
then Result := Value2
else Result := Value1 and (Value2.Value = ebTrue);
// or if to accept a duplicate redundant check for readability sake
// and to avert potential later erros (refactoring, you may accidentally remove the check above)
// else Result := Value1 and boolean (Value2);
end;
等
PS。上記の未指定のチェックは、意図的に悲観的になり、悪い方向に進む傾向があります。これは、初期化されていない変数と将来の変更の可能性に対する防御であり、3 つ以上の状態を追加します。これは過剰に保護しているように見えるかもしれませんが、少なくとも Delphi XE2 は mee に同意しています: 同様のケースの警告を参照してください:
program Project20; {$APPTYPE CONSOLE}
uses System.SysUtils;
type enum = (e1, e2, e3);
var e: enum;
function name( e: enum ): char;
begin
case e of
e1: Result := 'A';
e2: Result := 'B';
e3: Result := 'C';
end;
end;
// [DCC Warning] Project20.dpr: W1035 Return value of function 'name' might be undefined
begin
for e := e1 to e3
do Writeln(name(e));
ReadLn;
end.