将泛型与不同的约束结合起来 [英] Combining generics with different constraints

查看:87
本文介绍了将泛型与不同的约束结合起来的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个原子乐观初始化类:

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方法,您可以使用 TypeInfo 功能:

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;

这篇关于将泛型与不同的约束结合起来的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆