Delphi-PRAXiS
Seite 3 von 3     123   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Methoden-Parameter soll Referenz, aber kein nil sein können (https://www.delphipraxis.net/177808-methoden-parameter-soll-referenz-aber-kein-nil-sein-koennen.html)

himitsu 29. Nov 2013 10:13

AW: Methoden-Parameter soll Referenz, aber kein nil sein können
 
Zwar nicht im Compiler, aber zur Laufzeit sollte es gehen?
Delphi-Quellcode:
type
  TSimpleNonNullable<T> = record
    class operator Implicit(const Value: TSimpleNonNullable<T>): T; inline;
    class operator Implicit(const Value: T): TSimpleNonNullable<T>; inline;
    class procedure Check(const Value: T); inline; static;
  public type
    ENonNullable = class(Exception);
  private
    FValue: T;
  end;

{ TSimpleNonNullable<T> }

class operator TSimpleNonNullable<T>.Implicit(const Value: TSimpleNonNullable<T>): T;
begin
  Check(Value);
  Result := Value.FValue;
end;

class operator TSimpleNonNullable<T>.Implicit(const Value: T): TSimpleNonNullable<T>;
begin
  Check(Value);
  Result.FValue := Value;
end;

class procedure TSimpleNonNullable<T>.Check(const Value: T);
begin
  case SizeOf(Value) of
    4:  if PInteger(@Value)^ <> 0 then Exit;
    8:  if PInt64(@Value)^   <> 0 then Exit;
    else raise ENonNullable.CreateFmt('TNonNullable<T>: Type %s is not supported.', [GetTypeName(TypeInfo(T))]);
  end;
  raise ENonNullable.CreateFmt('TNonNullable<T>: Variable %s(%p) is null.', [GetTypeName(TypeInfo(T)), @Value]);
end;
Delphi-Quellcode:
uses
  TypInfo, Variants;

type
  TNonNullable<T> = record
    class operator Implicit(const Value: TNonNullable<T>): T; inline;
    class operator Implicit(const Value: T): TNonNullable<T>; inline;
    class procedure Check(const Value: T); static;
  public type
    ENonNullable = class(Exception);
  private
    FValue: T;
  end;

{ TNonNullable<T> }

class procedure TNonNullable<T>.Check(const Value: T);
begin
  case PTypeInfo(TypeInfo(T)).Kind of
    tkPointer, tkClass, tkClassRef, tkInterface, tkProcedure, tkString, tkUString, tkDynArray, tkWString:
      if PPointer(@Value)^ <> nil then
        Exit;
    tkInteger, tkChar, tkWChar, tkEnumeration, tkSet:
      case GetTypeData(TypeInfo(T)).OrdType of
        otSByte, otUByte:
          if PByte(@Value)^ <> 0 then
            Exit;
        otSWord, otUWord:
          if PWord(@Value)^ <> 0 then
            Exit;
        otSLong, otULong:
          if PLongWord(@Value)^ <> 0 then
            Exit;
        else
          raise ENonNullable.CreateFmt('TNonNullable<T>: Type %s is not supported.', [GetTypeName(TypeInfo(T))]);
      end;
    tkInt64:
      if PInt64(@Value)^ <> 0 then
        Exit;
    tkFloat:
      case GetTypeData(TypeInfo(T)).FloatType of
        ftSingle:
          if PSingle(@Value)^ <> 0 then
            Exit;
        ftDouble:
          if PDouble(@Value)^ <> 0 then
            Exit;
        ftExtended:
          if PExtended(@Value)^ <> 0 then
            Exit;
        ftCurr:
          if PCurrency(@Value)^ <> 0 then
            Exit;
        else
          raise ENonNullable.CreateFmt('TNonNullable<T>: Type %s is not supported.', [GetTypeName(TypeInfo(T))]);
      end;
    tkMethod:
      if TMethod(Pointer(@Value)^).Code <> nil then
        Exit;
    tkVariant:
      if not VarIsNull(PVariant(@Value)^) and VarIsEmpty(PVariant(@Value)^) then
        Exit;
    else
      raise ENonNullable.CreateFmt('TNonNullable<T>: Type %s is not supported.', [GetTypeName(TypeInfo(T))]);
  end;

  raise ENonNullable.CreateFmt('TNonNullable<T>: Variable %s(%p) is null.', [GetTypeName(TypeInfo(T)), @Value]);
end;

class operator TNonNullable<T>.Implicit(const Value: TNonNullable<T>): T;
begin
  Check(Value.FValue);
  Result := Value.FValue;
end;

class operator TNonNullable<T>.Implicit(const Value: T): TNonNullable<T>;
begin
  Check(Value);
  Result.FValue := Value;
end;

Der schöne Günther 29. Nov 2013 10:19

AW: Methoden-Parameter soll Referenz, aber kein nil sein können
 
Parametrisierte, operator-überladene Records. Jetzt habe ich alles gesehen. :roteyes:

himitsu 29. Nov 2013 11:37

AW: Methoden-Parameter soll Referenz, aber kein nil sein können
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1237896)
Parametrisierte, operator-überladene Records. Jetzt habe ich alles gesehen. :roteyes:

Ich hatte hier vor Jahren mal irgendwo eine Codezeile gepostet, die sah aus wie ein C++-Code, oder eher wie soein obfuscateter JavaScript-Code.
Aber im Grunde war es nur eine For-Step-Schleife, wie man sie aus QBasic kennt, welche aus anonymen Methoden bestand, vielleicht noch mit bissl Generics und alles "schön" als Einzeiler.
Delphi-Quellcode:
FOR X% = 0 TO 9 STEP 3  // 0 3 6 9 

FOR X% = 3 TO 0 STEP -1  // 3 2 1 0
Aber leider finde ich den einfach nicht mehr :cry:


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:03 Uhr.
Seite 3 von 3     123   

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz