我想缩短以下代码:
procedure TAddInModule.FinanBladCalculate(Sender: TObject);
begin
if (Sender is TExcelWorksheet) then begin
(Sender as TExcelWorksheet).Tag:= TagCalculationDone;
// or
TExcelWorksheet(Sender).Tag:= TagCalculationDone;
end
else {do nothing}
end;
我做了很多这是/作为检查,只是为了安全起见 然而,这是很多打字,只是为了安全演员。
有没有办法缩短这个并获得相同的结果? 我正在考虑使用记录和运算符重载的通用解决方案。
以下代码有效:
program Project41;
{$APPTYPE CONSOLE}
uses
System.SysUtils,VCL.Forms;
type
AsIs<T: class> = record
Data: T;
class operator Implicit(const a: TObject): AsIs<T>;
function OK: boolean;
end;
function AsIs<T>.OK: boolean;
begin
Result:= Assigned(Data);
end;
class operator AsIs<T>.Implicit(const a: TObject): AsIs<T>;
begin
if a is T then Result.Data:= T(a)
else Result.Data:= nil;
end;
procedure Demonstrate(Sender: TObject);
var
Test: AsIs<TApplication>;
begin //Something silly to demonstrate
Test:= Sender;
if Test.OK then Test.Data.HandleMessage;
end;
begin
Demonstrate(Application);
end.
有没有办法让它更短? 类似的东西:
Test(App).Data.HandleMessage;
//or even
Test(App).HandleMessage;
答案 0 :(得分:6)
有一种观点认为,代码应该将GUI和逻辑分开,就像在MVC模式中一样,因此事件处理程序不应包含任何实际工作,而只是将用户的活动路由到实际的业务逻辑实现者,如
procedure TAddInModule.Button1Click(Sender: TObject);
begin
if (Sender is TExcelWorksheet) then
FinanBladCalculate(TExcelWorksheet(Sender));
end;
procedure TAddInModule.FinanBladCalculate(Sheet: TExcelWorksheet);
begin
Sheet.Tag:= TagCalculationDone;
...
...
...
end;
这样以后会有更多的事件可以调用FinanBladCalculate
,实际工作负载集中并包含在那里(如菜单,热键,手势等)。
这种模式可能会在一定程度上使用该记录
procedure TAddInModule.Button1Click(Sender: TObject);
begin
FinanBladCalculate(Sender);
end;
procedure TAddInModule.MenuItem1Click(Sender: TObject);
begin
FinanBladCalculate(Sender);
end;
procedure TAddInModule.CheckBox1Check(Sender: TObject);
begin
FinanBladCalculate(Sender);
end;
....
procedure TAddInModule.FinanBladCalculate(const Sheet: AsIs<TExcelWorksheet>);
begin
if Sheet.Data = nil then exit;
Sheet.Data.Tag:= TagCalculationDone;
...
...
...
end;
如果您有许多可以启动某些工作并具有不同事件处理程序的GUI元素,那么这可能是有意义的。
答案 1 :(得分:6)
使用绝对。您仍然可以执行确保类型安全所需的警告,但绝对允许您使用声明性类型转换与内联类型转换或作为与其隐式,冗余是检查(如果您自己检查 类型,则是多余的):
var
excel: TExcelWorksheet absolute aSender;
begin
if aSender is TExcelWorksheet then
begin
excel.Tag := TagCalculationDone;
end;
end;
绝对声明使 excel 成为声明中引用的内存地址的类型同义词。即,没有额外的局部变量,也没有执行类型转换为该变量赋值的代码。而 excel 只是访问 aSender 价值的另一种方式。
您可以根据需要为同一地址添加任意数量的同义词同义词。因此,如果 aSender 也可以是 TWordDocument (或其他):
var
excel: TExcelWorksheet absolute aSender;
word: TWordDocument absolute aSender;
begin
if aSender is TExcelWorksheet then
begin
excel.Tag := TagCalculationDone;
end
else if aSender is TWordDocument then
begin
word.Tag := TagFieldsUpdated; // Or whatever
end;
end;
可以使用相同的技术为局部变量和参数创建此类同义词。