Einzelnen Beitrag anzeigen

Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#15

AW: ARC - Weak-Referenzen mit unterschiedlichem Verhalten bei ARC und Nicht-ARC

  Alt 23. Dez 2014, 20:22
Das möchtest du bestimmt einmal zeigen.
War eine Designstudie, war noch nie im realen Einsatz und ich hoffe ich hab auf die Schnelle auch die richtige Version erwischt.
Einfach nur die Referenzzählung deaktiviert, aber nichts mit automatischem nil.

Delphi-Quellcode:
type
  TWeakRef<Obj: class> = record
  private
    //FReference: {$IFDEF WEAKINSTREF}Obj{$ELSE}Pointer{$ENDIF};
    {$IFDEF WEAKINSTREF}
    FReference: Obj;
    {$ELSE}
    FReference: Pointer;
    {$ENDIF}
  public
    class operator Implicit(const Value: Obj): TWeakRef<Obj>; inline;
    class operator Implicit(const Value: TWeakRef<Obj>): Obj; inline;
  end;
  TWeakIntf<Intf: IInterface> = record
  private
    //FReference: {$IFDEF WEAKINTREF}Intf{$ELSE}Pointer{$ENDIF};
    {$IFDEF WEAKINTREF}
    FReference: Intf;
    {$ELSE}
    FReference: Pointer;
    {$ENDIF}
  public type
    PIntf = ^Intf;
  public
    class operator Implicit(const Value: Intf): TWeakIntf<Intf>; inline;
    class operator Implicit(const Value: TWeakIntf<Intf>): Intf; inline;
  end;

{ TWeakRef<Ref> }

class operator TWeakRef<Obj>.Implicit(const Value: Obj): TWeakRef<Obj>;
begin
  //Result.FReference := {$IFDEF WEAKINSTREF}Value{$ELSE}Pointer(Value){$ENDIF};
  {$IFDEF WEAKINSTREF}
  Result.FReference := Value;
  {$ELSE}
  Result.FReference := Pointer(Value);
  {$ENDIF}
end;

class operator TWeakRef<Obj>.Implicit(const Value: TWeakRef<Obj>): Obj;
begin
  //Result := {$IFDEF WEAKINSTREF}Value.FReference{$ELSE}Obj(Value.FReference){$ENDIF};
  {$IFDEF WEAKINSTREF}
  Result := Value.FReference;
  {$ELSE}
  Result := Obj(Value.FReference);
  {$ENDIF}
end;

{ TWeakIntf<Intf> }

class operator TWeakIntf<Intf>.Implicit(const Value: Intf): TWeakIntf<Intf>;
begin
  //Result.FReference := {$IFDEF WEAKINTREF}Value{$ELSE}PPointer(@Value)^{$ENDIF};
  {$IFDEF WEAKINTREF}
  Result.FReference := Value;
  {$ELSE}
  Result.FReference := PPointer(@Value)^;
  {$ENDIF}
end;

class operator TWeakIntf<Intf>.Implicit(const Value: TWeakIntf<Intf>): Intf;
begin
  //Result := {$IFDEF WEAKINTREF}Value.FReference{$ELSE}PIntf(@Value.FReference)^{$ENDIF};
  {$IFDEF WEAKINTREF}
  Result := Value.FReference;
  {$ELSE}
  Result := PIntf(@Value.FReference)^;
  {$ENDIF}
end;
Nix Großes ... im Grunde einfach nur die manuellen Casts im Generic verpackt.


Generics und unterschiedliche DEFINEs funktioniert nicht.
Außerdem erlauben Generics nur UND-Einschränkungen. (Object ODER Interface)
Auch wenn WEAKINTREF und WEAKINSTREF bisher scheinbar immer gleich eingestellt sind, weiß ich nicht was in Zukunft passiert.

Sonst hätte eine einzige Klasse gereicht. (per Code zur Laufzeit den Typ zu prüfen wollte ich nicht)
Und nicht über die Kommentare wundern, aber die Parser von Error-Insight und Docu-Insight sind sowas von schrottig, daß ich den Originalcode aufteilen musste.


[add]
Ein Code ala
Delphi-Quellcode:
type
  TWeak<Ref: class, interface> = record
  private
    FReference: {$IF Define(WEAKINSTREF) and (TypeInfo(Ref).Kint = tkClass)
      or Define(WEAKINTREF) and (TypeInfo(Ref).Kint = tkInterface)}
Obj{$ELSE}Pointer{$IFEND};
  public
    class operator Implicit(const Value: Ref): TWeak<Ref>; inline;
    class operator Implicit(const Value: TWeak<Ref>): Ref; inline;
  end;

{ TWeak<Ref> }

class operator TWeak<Ref>.Implicit(const Value: Ref): TWeak<Ref>;
begin
  Result.FReference := {$IF Define(WEAKINSTREF) and (TypeInfo(Ref).Kint = tkClass)
    or Define(WEAKINTREF) and (TypeInfo(Ref).Kint = tkInterface)}
Value{$ELSE}Pointer(Value){$IFEND};
end;

class operator TWeak<Ref>.Implicit(const Value: TWeak<Ref>): Ref;
begin
  Result := {$IF Define(WEAKINSTREF) and (TypeInfo(Ref).Kint = tkClass)
    or Define(WEAKINTREF) and (TypeInfo(Ref).Kint = tkInterface)}
Value.FReference{$ELSE}Ref(Value.FReference){$IFEND};
end;
wäre cooler gewesen.


Ab TComponent lässt sich ein schön kleiner Code für eine selbst-auf-nil-setzende Objektvariable realisieren. (ansonsten isses nur ein bissl umständlicher)
$2B or not $2B

Geändert von himitsu (23. Dez 2014 um 20:43 Uhr)
  Mit Zitat antworten Zitat