CharInSet Compiler Warning in Delphi XE4

前端 未结 3 523
甜味超标
甜味超标 2021-02-06 10:25

I have following statement in my Delphi 7 code.

TMyCharSet = set of char;

When I migrated that code to Delphi XE4, I am getting following compi

3条回答
  •  忘了有多久
    2021-02-06 11:00

    A set cannot contain items larger than a byte. Since Char in UniCode Delphi is a WideChar which is two bytes in size, a set type is an inappropriate container.

    Here is an example of a generic set type based on a record, TSet. This means that you don't have to think about creation and destruction of variables of this type. Use this type as a container for simple types. I tried to mimic most of the behavior of the set type. Addition and subtraction of items can be done with + and - operators. Added the in operator as well.

    Note: The record holds the data in a dynamic array. Assigning a variable to another will make both variables using the same dynamic array. A Copy-On-Write (COW) protection built-in will prevent a change in one variable to be reflected on the other one.

    unit GenericSet;
    
    interface
    
    Uses
      System.Generics.Defaults;
    
    Type
      TSet = record
        class operator Add(const aSet: TSet; aValue: T) : TSet; overload;
        class operator Add(const aSet: TSet; const aSetOfT: TArray) : TSet; overload;
        class operator Add(const aSet1: TSet; const aSet2: TSet) : TSet; overload;
        class operator Subtract(const aSet: TSet; aValue: T): TSet; overload;
        class operator Subtract(const aSet: TSet; const aSetOfT: TArray) : TSet; overload;
        class operator Subtract(const aSet1: TSet; const aSet2: TSet) : TSet; overload;
        class operator In(aValue: T; const aSet: TSet): Boolean; overload;
        class operator In(const aSetOf: TArray; const aSet: TSet): Boolean; overload;
        class operator In(const aSet1: TSet; const aSet2: TSet): Boolean; overload;
      private
        FSetArray : TArray;
        function GetEmpty: Boolean;
      public
        procedure Add(aValue: T);
        procedure AddSet(const setOfT: array of T); overload;
        procedure AddSet(const aSet: TSet); overload;
        procedure Remove(aValue: T);
        procedure RemoveSet(const setOfT: array of T); overload;
        procedure RemoveSet(const aSet : TSet); overload;
        function Contains(aValue: T): Boolean; overload;
        function Contains(const aSetOfT: array of T): Boolean; overload;
        function Contains(const aSet : TSet): Boolean; overload;
        procedure Clear;
        property Empty: Boolean read GetEmpty;
      end;
    
    implementation
    
    procedure TSet.Add(aValue: T);
    begin
      if not Contains(aValue) then begin
        SetLength(FSetArray,Length(FSetArray)+1);
        FSetArray[Length(FSetArray)-1] := aValue;
      end;
    end;
    
    class operator TSet.Add(const aSet: TSet; aValue: T): TSet;
    begin
      Result.AddSet(aSet.FSetArray);
      Result.Add(aValue);
    end;
    
    class operator TSet.Add(const aSet: TSet; const aSetOfT: TArray): TSet;
    begin
      Result.AddSet(aSet.FSetArray);
      Result.AddSet(aSetOfT);
    end;
    
    class operator TSet.Add(const aSet1, aSet2: TSet): TSet;
    begin
      Result.AddSet(aSet1.FSetArray);
      Result.AddSet(aSet2.FSetArray);
    end;
    
    procedure TSet.AddSet(const setOfT: array of T);
    var
      i : Integer;
    begin
      for i := 0 to High(setOfT) do
        Self.Add(setOfT[i]);
    end;
    
    procedure TSet.AddSet(const aSet: TSet);
    begin
      AddSet(aSet.FSetArray);
    end;
    
    procedure TSet.RemoveSet(const setOfT: array of T);
    var
      i : Integer;
    begin
      for i := 0 to High(setOfT) do
        Self.Remove(setOfT[i]);
    end;
    
    procedure TSet.RemoveSet(const aSet: TSet);
    begin
      RemoveSet(aSet.FSetArray);
    end;
    
    class operator TSet.Subtract(const aSet1, aSet2: TSet): TSet;
    begin
      Result.AddSet(aSet1.FSetArray);
      Result.RemoveSet(aSet2.FSetArray);
    end;
    
    class operator TSet.Subtract(const aSet: TSet;
      const aSetOfT: TArray): TSet;
    begin
      Result.AddSet(aSet.FSetArray);
      Result.RemoveSet(aSetOfT);
    end;
    
    class operator TSet.Subtract(const aSet: TSet; aValue: T): TSet;
    begin
      Result.AddSet(aSet.FSetArray);
      Result.RemoveSet(aValue);
    end;
    
    class operator TSet.In(aValue: T; const aSet: TSet): Boolean;
    begin
      Result := aSet.Contains(aValue);
    end;
    
    class operator TSet.In(const aSetOf: TArray; const aSet: TSet): Boolean;
    begin
      Result := aSet.Contains(aSetOf);
    end;
    
    class operator TSet.In(const aSet1: TSet; const aSet2: TSet): Boolean;
    begin
      Result := aSet2.Contains(aSet1.FSetArray);
    end;
    
    function TSet.Contains(aValue: T): Boolean;
    var
      i : Integer;
      c : IEqualityComparer;
    begin
      c := TEqualityComparer.Default;
      Result := false;
      for i := 0 to Length(FSetArray)-1 do
        if c.Equals(FSetArray[i],aValue) then
          Exit(True);
    end;
    
    function TSet.GetEmpty: Boolean;
    begin
      Result := (Length(FSetArray) = 0);
    end;
    
    procedure TSet.Clear;
    begin
      SetLength(FSetArray,0);
    end;
    
    function TSet.Contains(const aSetOfT: array of T): Boolean;
    var
      i : Integer;
    begin
      Result := High(aSetOfT) >= 0;
      for i := 0 to High(aSetOfT) do
      begin
        Result := Contains(ASetOfT[i]);
        if not Result then
          Exit(false);
      end;
    end;
    
    function TSet.Contains(const aSet: TSet): Boolean;
    begin
      Result := Contains(aSet.FSetArray);
    end;
    
    procedure TSet.Remove(aValue: T);
    var
      i : Integer;
      c : IEqualityComparer;
    begin
      c := TEqualityComparer.Default;
      for i := 0 to Length(FSetArray)-1 do
      begin
        if c.Equals(FSetArray[i],aValue) then
        begin
          SetLength(FSetArray,Length(FSetArray)); // Ensure unique dyn array
          if (i < Length(FSetArray)-1) then
            FSetArray[i] := FSetArray[Length(FSetArray)-1]; // Move last element
          SetLength(FSetArray,Length(FSetArray)-1);
          Break;
        end;
      end;
    end;
    
    end.
    

    A sample test program:

    program ProjectGenericSet;
    {$APPTYPE CONSOLE}    
    uses
      GenericSet in 'GenericSet.pas';
    
    var
     mySet,mySet1 : TSet;
    begin
      mySet.AddSet(['A','B','C']);
      WriteLn(mySet.Contains('C'));
      WriteLn(mySet.Contains('D'));  // False
      mySet := mySet + 'D';
      WriteLn(mySet.Contains('D'));
      WriteLn('D' in mySet);
      mySet := mySet - 'D';
      WriteLn(mySet.Contains('D'));  // False
      mySet := mySet + TArray.Create('D','E');
      WriteLn(mySet.Contains('D'));
      WriteLn(mySet.Contains(['A','D']));
      mySet1 := mySet;
      // Testing COW
      mySet1.Remove('A');
      WriteLn(mySet.Contains('A'));
      mySet1:= mySet1 + mySet;
      WriteLn(mySet1.Contains('A'));
      mySet := mySet1;
      mySet1.Clear;
      WriteLn(mySet.Contains('A'));
      ReadLn;
    end.
    

提交回复
热议问题