Конференция "Компоненты" » Как изменить одно из полей массива записей компонента? [D7, WinXP]
 
  • Mr.Devil © (02.04.10 02:36) [0]
    У компонента есть свойство, представлющее из себя массив записей с числовой индексацией. Хочу изменить только одно из свойств записи из массива:
    UsersList[c].State:=isIdle;


    [Pascal Error] Unit1.pas(258): E2064 Left side cannot be assigned to

    Что нужно поменять или как лучше это сделать по-другому?

    код компонента:

    type
     TState = (isIgnore, isInstructed, isIdle, isChating);

     TUser = packed record
       P1: cardinal;
       P2: String;
       P3: TState;
       P4: String;
     end;

     TAUser = array of TUser;

     TUsersList = class
     private
       FUsers: TAUser;
       FCount: integer;
       function FUserRead(P1: Cardinal):TUser;
       procedure FUserWrite(P1: Cardinal; const User:TUser);
     public
       ...
       function UserIndex(P1: Cardinal):integer;
       property User[P1: Cardinal]:TUser
         read  FUserRead
         write FUserWrite; default;
     end;

    implementation
    ...
    function TUsersList.UserIndex(P1: Cardinal):integer;
    var
     i:integer;
    begin
     Result:=-1; // если не найдем будет -1
     for i:=0 to FCount - 1 do begin
       if FUsers[i].P1=P1 then begin
         Result:=i;
         Break;
       end;
     end;
    end;

    function TUsersList.FUserRead(P1: Cardinal):TUser;
    var
     n:integer;
    begin
     n:=UserIndex(P1);
     if (n<0) OR (n>=FCount) then raise EUsersListError.CreateFmt(SUsersListIndexError, [n]);
     Result:=FUsers[n];
    end;

    procedure TUsersList.FUserWrite(P1: Cardinal; const User:TUser);
    var
     n:integer;
    begin
     n:=UserIndex(P1);
     if (n>0) AND (n<FCount) then begin
     // такой номер уже есть в списке
       FUsers[n]:=User;
     end
     else begin
     // такого номера еще нет в списке
       inc(FCount);
       SetLength(FUsers,FCount);
       FUsers[FCount-1]:=User;
     end;
    end;

  • DimaBr © (02.04.10 09:03) [1]
    Возможны 2 варианта:
    1.
    UsersList[c] := Function(P1,P2,isIdle,P4);


    2.
    property UserState[Index: integer]:TState read GetUserState write SetUserState;

  • DimaBr © (02.04.10 15:47) [2]
    По коду:
    1. Методы доступа принято именовать Get... и Set...
    2. Проверка
    if n>=FCount then

    просто лишняя
    3. Поле FCount - лишнее
    4. Функцию UserIndex можно сделать короче
    function TUsersList.UserIndex(P1: Cardinal):integer;
    begin
    for Result := 0 to High(FUsers) do
      if FUsers[Result].P1=P1 then Exit;
     Result:=-1; // если не найдем будет -1
    end;

  • Mr.Devil © (02.04.10 21:14) [3]
    Спасибо, воспользовался вторым вариантом :)
  • Mr.Devil © (02.04.10 21:22) [4]

    > 1. Методы доступа принято именовать Get... и Set...

    Уже сам исправил, поздно ночью уже плохо соображал :)

    > 2. Проверка
    if n>=FCount

    then просто лишняя

    Имеется ввиду  
    if (n<0) OR (n>=FCount) then raise ...

    ?

    > 3. Поле FCount - лишнее

    Спасибо, не знал что так можно
    High(FUsers)

    :)

    > 4. Функцию UserIndex можно сделать короче

    Учту.
  • Дмитрий Белькевич (16.05.10 16:26) [5]

    > if (n<0) OR (n>=FCount)


    Можно еще так: if not InRange(n, 0, FCount - 1) then ...
    если с краями не напутал.
  • alexrayne (18.05.10 22:20) [6]
    TUser = packed record
      P1: cardinal;
      P2: String;
      P3: TState;
      P4: String;
    end;


    запись то у вас немаленькая. она полюбому бедет передаваться адресом, посему я бы сделал свойство ваше вместо массива записей - массивом адресов на запись. в таком случае
    UsersList[c].State:=isIdle;


    становится нормальным и компилируемым
    тобиш я бы сдела чтото вроде етого:

    SomeUserData = packed record
      P1: cardinal;
      P2: String;
      P3: TState;
      P4: String;
    end;
    SomeUserDataAccess = ^SomeUserData;

    TAUser = array of TUser;

    TUsersList = class
    private
      FUsers: TAUser;
      FCount: integer;
      function FUserRead(P1: Cardinal):SomeUserDataAccess;
      procedure FUserWrite(P1: Cardinal; const User:SomeUserDataAccess);
    public
      ...
      function UserIndex(P1: Cardinal):integer;
      property User[P1: Cardinal]:SomeUserDataAccess
        read  FUserRead
        write FUserWrite; default;
    end;

    procedure TUsersList.FUserWrite(P1: Cardinal; const User:SomeUserDataAccess);
    var
    n:integer;
    begin
    n:=UserIndex(P1);
    if (n>0) AND (n<FCount) then begin
    // такой номер уже есть в списке
      FUsers[n]:=User;
    end
    else begin
    // такого номера еще нет в списке
      inc(FCount);
      SetLength(FUsers,FCount);
      FUsers[FCount-1]:=User^;
    end;
    end;

  • alexrayne (18.05.10 22:23) [7]
    конешно напортачил, но мысль вроде засветил
 
Конференция "Компоненты" » Как изменить одно из полей массива записей компонента? [D7, WinXP]
Есть новые Нет новых   [120273   +39][b:0][p:0.003]