不同的约束

不同的约束

问题描述:

我有这样的原子乐观初始化类仿制药相结合:不同的约束

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; 

现在我想执行的对象相同的模式。

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,我理想喜欢用这个作为

var 
    o: TObject; 
    i: IInterface; 

Atomic<TObject>.Initialize(o, CreateObject); 
Atomic<IInterface>.Initialize(i, CreateInterface); 

我找不到任何好的解决方案。我得到的唯一想法是声明类为Atomic<T>(没有约束),然后以某种方式(不知道如何)在运行时检查T的RTTI并相应地继续。

我不太喜欢这个想法,我正在寻找更好的方法。

看来你不能指定“类或接口”类型的约束。因此,最简单的解决方案似乎是放弃约束(您可以使用RTTI在运行时强制执行它)。

对于RTTI的方法,你可以使用TypeInfo功能:

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; 
+0

这似乎工作正常,谢谢! – gabr

+0

欢迎,@ gabr,我很高兴能帮上忙! –

一个强类型的解决方案是两个泛型类包装成另一个类为操作

type 
    Atomic = class 
    type 
     Intf<T: IInterface> = class 
     type TFactory = reference to function: T; 
     class function Initialize(var storage: T; factory: TFactory): T; 
     end; 
     Obj<T: class> = class 
     type TFactory = reference to function: T; 
     class function Initialize(var storage: T; factory: TFactory): T; 
     end; 
    end; 
提供公共的命名空间

用法于:

var 
    o: TObject; 
    i: IInterface; 

Atomic.Obj<TObject>.Initialize(o, CreateObject); 
Atomic.Intf<IInterface>.Initialize(i, CreateInterface); 
+0

这也是一个不错的解决方案! –