【问题标题】:Why can some arrays be published but not others?为什么有些数组可以发布而其他数组不能发布?
【发布时间】:2010-10-10 05:53:54
【问题描述】:
type
   TStaticArray = array[1..10] of integer;
   TDynamicArray = array of integer;

   TMyClass = class(TObject)
   private
      FStaticArray: TStaticArray;
      FDynamicArray: TDynamicArray;
   published
      property staticArray: TStaticArray read FStaticArray write FStaticArray; //compiler chokes on this
      property dynamicArray: TDynamicArray read FDynamicArray write FDynamicArray; //compiler accepts this one just fine
   end;

这里发生了什么?静态数组给出错误,“发布的属性'staticArray'不能是数组类型”但动态数组就可以了吗?我糊涂了。任何人都知道这背后的原因,以及我该如何解决它? (不,我不想将我所有的静态数组重新声明为动态数组。它们的大小是有原因的。)

【问题讨论】:

    标签: delphi arrays properties delphi-2009


    【解决方案1】:
     TMyClass = class(TObject)
       private
         FStaticArray: TStaticArray;
         FIdx: Integer;
         function  GetFoo(Index: Integer): Integer;
         procedure SetFoo(Index: Integer; Value: Integer);
       public
         property Foo[Index: Integer] : Integer read GetFoo write SetFoo;
       published
         property Idx: Integer read fidx write fidx;
         property AFoo: Integer read GetAFoo writte SetAFoo;
       end;
    implementation
    function TMyClass.GetAFoo: Integer;
    begin
      result := FStaticArray[FIdx];
    end;
    procedure TMyClass.SetAFoo(Value: Integer);
    begin
      FStaticArray[FIdx] := Value;
    end;
    

    【讨论】:

    • 这并不能准确地告诉我们关于 WHY 的任何信息。
    【解决方案2】:

    你必须有 getter 和 setter。在 D2009 下(没有检查其他版本),getter/setter 的参数由于某种原因不能是 const。 ?

    这在 D2009 下运行良好:

    type
      TMyArray = array[0..20] of string;
    
    type
      TMyClass=class(TObject)
      private
        FMyArray: TMyArray;
        function GetItem(Index: Integer): String;
        procedure SetItem(Index: Integer; Value: string);
      public
        property Items[Index: Integer]: string read GetItem write SetItem;
      end;
    
    implementation
    
    function TMyClass.GetItem(Index: Integer): string;
    begin
      Result := '';
      if (Index > -1) and (Index < Length(FMyArray)) then
        Result := FMyArray[Index];
    end;
    
    procedure TMyClass.SetItem(Index: Integer; Value: string);
    begin
      if (Index > -1) and (Index < Length(FMyArray)) then
        FMyArray[Index] := Value;
    end;
    

    注意:显然,我通常不会忽略超出范围的索引值。这是一个如何在类定义中创建静态数组属性的快速示例; IOW,这只是一个可编译的示例。

    【讨论】:

      【解决方案3】:

      无法发布数组属性。 所以下面的代码不起作用。解决方法可能是使其成为public

         TMyClass = class(TObject)
         private
           FStaticArray: TStaticArray;
      
           function  GetFoo(Index: Integer): Integer;
           procedure SetFoo(Index: Integer; Value: Integer);
         public
           property Foo[Index: Integer] : Integer read GetFoo write SetFoo;
         end;
      

      【讨论】:

      • 如果不使用 TStaticArray 作为属性,如何得到同样的错误?
      • 因为它仍然是一个数组属性。我不赞成 Gortok 的一个原因:这是一个明显不正确的答案。 (插入它,它不会编译。)
      • 梅森说得对。您不能发布数组属性。这就是它的工作方式......
      • 您的示例是错误的,因为您仍然将数组属性留在已发布部分,而不是公开(这会起作用)。请编辑以更正,我不会投反对票。 :-)
      【解决方案4】:

      Published 声明告诉编译器将信息存储在虚拟方法表中。只能存储某些类型的信息。
      已发布属性的类型不能是指针、记录或数组。如果是集合类型,则必须足够小才能存储为整数。
      (奥莱利,简而言之,德尔菲)

      【讨论】:

      • 只有一个精度:记录不能用作已发布的属性。或者实际上是允许的,但是这个字段没有附加RTTI。因此,在已发布的属性部分中添加记录将毫无用处。而在 RTTI 中允许和处理动态数组。
      【解决方案5】:

      您可以发布动态数组属性的原因是动态数组被实现为引用或“隐式指针”。它们的工作方式更像字符串,真的。

      不能发布静态数组的原因,我不知道。这就是它的制作方式,我猜..

      有关动态数组如何工作的更多详细信息,请查看DrBobs site

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-05-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-14
        • 1970-01-01
        • 2021-05-21
        • 2011-12-31
        相关资源
        最近更新 更多