问题描述
我有这个原子乐观初始化类:
I have this atomic optimistic initializer class:
type
Atomic<T: IInterface> = class
type TFactory = reference to function: T;
class function Initialize(var storage: T; factory: TFactory): T;
end;
class function Atomic<T>.Initialize(var storage: T; factory: TFactory): T;
var
tmpIntf: T;
begin
if not assigned(storage) then begin
tmpIntf := factory();
if InterlockedCompareExchangePointer(PPointer(@storage)^, PPointer(@tmpIntf)^, nil) = nil then
PPointer(@tmpIntf)^ := nil;
end;
Result := storage;
end;
现在我想为对象实现相同的模式。
Now I would like to implement the same pattern for objects.
type
Atomic<T: class> = class
type TFactory = reference to function: T;
class function Initialize(var storage: T; factory: TFactory): T;
end;
class function Atomic<T>.Initialize(var storage: T; factory: TFactory): T;
var
tmpIntf: T;
begin
if not assigned(storage) then begin
tmpIntf := factory();
if InterlockedCompareExchangePointer(PPointer(@storage)^, PPointer(@tmpIntf)^, nil) = nil then
tmpIntf.Free;
end;
Result := storage;
end;
我可以在两个不同的类中完成这两个,但是我真的想将两个初始值设置为同样的伞。 IOW,我最好喜欢用它作为
I can do those two in two separate classes, but I would really like to put both initializers under the same umbrella. IOW, I would ideally like to use this as
var
o: TObject;
i: IInterface;
Atomic<TObject>.Initialize(o, CreateObject);
Atomic<IInterface>.Initialize(i, CreateInterface);
我无法为此找到任何好的解决方案。我得到的唯一想法是将类声明为 Atomic< T>
(没有约束),然后以某种方式(不知道如何)在运行时检查T的RTTI,
I can't find any good solution for this. The only idea I got is to declare class as Atomic<T>
(without constraints) and then somehow (don't yet know how) check the RTTI of T in runtime and proceed accordingly.
我不喜欢这个想法,我正在寻找更好的方法。
I don't like this idea much and I'm looking for a better approach.
推荐答案
看来你不能指定类或接口类型的约束。因此,最简单的解决方案似乎是放弃约束(您可以在运行时使用RTTI强制执行它)。
It seems you cannot specify constraints of the type "class or interface". Therefore the easiest solution seems to be to drop the constraint (you can enforce it at runtime, using RTTI).
对于RTTI方法,您可以使用功能:
For the RTTI approach, you can use the TypeInfo
function:
uses
..., TypInfo;
class function Atomic<T>.Initialize(var storage: T; factory: TFactory): T;
var
tmpT: T;
begin
if not assigned(PPointer(@storage)^) then begin
tmpT := factory();
if InterlockedCompareExchangePointer(PPointer(@storage)^, PPointer(@tmpT)^, nil) = nil then begin
case PTypeInfo(TypeInfo(T))^.Kind of
tkInterface:
PPointer(@tmpT)^ := nil;
tkClass:
TObject(tmpT).Free;
else
raise Exception.Create('Atomic<T>.Initialize: Unsupported type');
end;
end;
end;
Result := storage;
end;
这篇关于将泛型与不同的约束结合起来的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!