gpt4 book ai didi

delphi - 如何将通用过程 TProc 作为参数传递并调用它?

转载 作者:行者123 更新时间:2023-12-03 15:32:09 27 4
gpt4 key购买 nike

我有一个日志记录类,它链接到许多模块。这个类的main方法是一个类方法:

type
TSeverity = (seInfo, seWarning, seError);

TLogger = class
class procedure Log(AMessage: String; ASeverity: TSeverity);
end;

在其他地方,我有一个函数 DoSomething() ,它可以执行一些我想记录的事情。但是,我不想将记录器的所有模块链接到声明“DoSomething()”以使用记录器的模块。相反,我想传递任意日志记录方法作为 DoSomething 的参数并从其主体中调用它。

问题是 TLogger.Log 需要在记录器类中定义的 TSeverity 类型的参数。所以我无法定义类型:

type
TLogProcedure = procedure(AMessage: String; ASverity: TSeverity) of Object;

因为我必须包含一个声明 TSeverity 的单元。

我试图根据通用程序提出一些解决方案,但我陷入困境。

uses
System.SysUtils;

type
TTest = class
public
class function DoSomething<T1, T2>(const ALogProcedure: TProc<T1,T2>): Boolean; overload;
end;

implementation

class function TTest.DoSomething<T1, T2>(const ALogProcedure: TProc<T1, T2>): Boolean;
var
LMessage: String;
LSeverity: Integer;
begin
//Pseudocode here I would like to invoke logging procedure here.
ALogProcedure(T1(LMessage), T2(LSeverity));
end;

代码中的其他地方我想使用DoSomething

begin
TTest.DoSomething<String, TSeverity>(Log);
end;

感谢您的帮助。

更新

可能是我没说清楚。

unit uDoer;

interface

type
TLogProcedure = procedure(AMessage: String; AErrorLevel: Integer) of Object;


// TDoer knows nothing about logging mechanisms that are used but it allows to pass ALogProcedure as a parameter.
// I thoight that I can somehow generalize this procedure using generics.
type
TDoer = class
public
class function DoSomething(const ALogProcedure: TLogProcedure): Boolean;
end;

implementation

class function TDoer.DoSomething(const ALogProcedure: TLogProcedure): Boolean;
begin
ALogProcedure('test', 1);
Result := True;
end;

end.

具有一种日志记录机制的独立单元。

unit uLogger;

interface

type
TSeverity = (seInfo, seWarning, seError);

// I know that I could solve my problem by introducing an overloaded method but I don't want to
// do it like this. I thought I can use generics somehow.

TLogger = class
class procedure Log(AMessage: String; ASeverity: TSeverity); {overload;}
{class procedure Log(AMessage: String; ASeverity: Integer); overload;}
end;

implementation

class procedure TLogger.Log(AMessage: String; ASeverity: TSeverity);
begin
//...logging here
end;

{class procedure TLogger.Log(AMessage: String; ASeverity: Integer);
begin
Log(AMessage, TSeverity(ASeverity));
end;}

end.

两个单元的使用示例。

implementation

uses
uDoer, uLogger;

procedure TForm10.FormCreate(Sender: TObject);
begin
TDoer.DoSomething(TLogger.Log); //Incompatible types: Integer and TSeverity
end;

最佳答案

在这里引入泛型没有帮助。您拥有的实际参数不是通用的。它们有固定类型:stringInteger。您传递给它们的函数不是通用函数,它接收 stringTSeverity 类型的参数。这些类型不匹配。

泛型在这里对你没有帮助,因为你的类型都是提前知道的。这里没有什么通用的。您需要做的就是在 IntegerTSeverity 之间进行转换。一旦你能做到这一点,你就可以调用你的函数了。

在您的情况下,您应该传递一个接受Integer的过程,因为您在调用该过程时没有可用的TSeverity。然后在该过程的实现中,您调用接受 TSeverity 的函数,这就是您进行转换的地方。

<小时/>

在涉及通用过程类型的场景中,您遇到的情况很常见。您有一个像这样的通用程序类型:

type
TMyGenericProcedure<T> = procedure(const Arg: T);

为了调用这样的过程,您需要一个 T 实例。如果您从 T 上通用的函数调用该过程,则您的参数也必须是通用的。在您的情况下,该参数不是通用的,它被固定为Integer。到那时,您使用泛型的尝试就会失败。

<小时/>

话虽如此,您所描述的内容根本没有真正联系在一起。如果您当时不知道 TSeverity 是什么,您怎么可能提出严重性参数呢?这对我来说没有任何意义。你怎么能仅仅想出一个整数值并希望它与这个枚举类型匹配呢?一些温和的重新设计将使您能够非常简单地完成此操作,而无需任何类型转换。

关于delphi - 如何将通用过程 TProc<T1,T2> 作为参数传递并调用它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39746475/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com