匿名方法本质上是与Invoke方法的接口:
type TProc = reference to procedure; IProc = interface procedure Invoke; end;
现在,是否有可能将它们分配给实际的接口变量或将其作为接口参数传递?
procedure TakeInterface(const Value: IInterface); begin end; var P: TProc; I: IInterface; begin I := P; // E2010 TakeInterface(P); // E2010 end;
[DCC32错误] E2010不兼容的类型:’IInterface’和’过程,无类型的指针或无类型参数’
问题:这是什么用例?
有很多对象在那里,不能简单地保持活着与接口参考.因此,他们被包裹在一个关闭并被毁坏与“Smart Pointers”:
type I<T> = reference to function : T; TInterfaced<T: class> = class (TInterfacedObject,I<T>) strict private FValue: T; function Invoke: T; // Result := FValue; public constructor Create(const Value: T); // FValue := Value; destructor Destroy; override; // FValue.Free; end; IInterfacedDictionary<TKey,TValue> = interface (I<TDictionary<TKey,TValue>>) end; TKey = String; TValue = String; var Dictionary: IInterfacedDictionary<TKey,TValue>; begin Dictionary := TInterfaced<TDictionary<TKey,TValue>> .Create(TDictionary<TKey,TValue>.Create); Dictionary.Add('Monday','Montag'); end; // FRefCount = 0,closure with object is destroyed
现在,有时不仅要保持一个单一的对象活着,还需要一个上下文.想像你有一个TDictionary< TKey,TValue>并从中抽出一个计数器:TEnumerator&TK; TEnumerator< TValue>或TEnumerator< TPair< TKey,TValue>>.或者字典包含和拥有TObjects.然后两者,新对象和字典的关闭将进入一个新的关闭,以便创建一个单独的独立引用:
type TInterfaced<IContext: IInterface; T: class> = class (TInterfacedObject,I<T>) strict private FContext: IContext; FValue: T; FFreeObject: Boolean; function Invoke: T; // Result := FValue; public constructor Create(const Context: IContext; const Value: T; const FreeObject: Boolean = True); // FValue = Value; FFreeObject := FreeObject; destructor Destroy; override; // if FFreeObject then FValue.Free; end; IInterfacedEnumerator<T> = interface (I<TEnumrator<T>>) end; TValue = TObject; // var Dictionary: IInterfacedDictionary<TKey,TValue>; Enumerator: IInterfacedEnumerator<TKey>; Obj: I<TObject>; begin Dictionary := TInterfaced<TDictionary<TKey,TValue>> .Create(TObjectDictionary<TKey,TValue>.Create([doOwnsValues])); Dictionary.Add('Monday',TObject.Create); Enumerator := TInterfaced< IInterfacedDictionary<TKey,TValue>,TEnumerator<TKey> >.Create(Dictionary,Dictionary.Keys.GetEnumerator); Obj := TInterfaced< IInterfacedDictionary<TKey,TObject >.Create(Dictionary,Dictionary['Monday'],False); Dictionary := nil; // closure with object still held alive by Enumerator and Obj. end;
现在的想法是融化TInterfaced< T>和TInterfaced< IContext,T>,这将使上下文的类型参数过时(一个界面就足够了),并导致这些主持人:
constructor TInterfaced<T: class>.Create(const Value: T; const FreeObject: Boolean = True); overload; constructor TInterfaced<T: class>.Create(const Context: IInterface; const Value: T; const FreeObject: Boolean = True); overload;
作为(纯)关闭可能不是使用匿名方法时会想到的主要用途.然而,它们的类型可以被给出为类的接口,其对象可以在关闭的破坏时进行清理,并且TFunc< T>使其流畅地访问其内容.虽然它们不共享共同的祖先,但似乎对类型的引用的值不能分配给接口类型,这意味着没有统一,安全和未来的方式来引用所有类型的闭包来保持它们的存活.