代码之家  ›  专栏  ›  技术社区  ›  Fabrizio RAHUL S R

“无法捕获符号”错误使用匿名方法中的开放数组参数,该方法被传递给另一个函数

  •  1
  • Fabrizio RAHUL S R  · 技术社区  · 4 年前

    我想用一个 array of Integer 作为参数传递给另一个函数的匿名方法中的参数:

    type
      TAnonymousMethod = reference to procedure();
    
    procedure SubTest(AMethod : TAnonymousMethod);
    begin
      AMethod();
    end;
    
    procedure Test(ACodes : array of Integer);
    begin
      SubTest(
        procedure()
        begin
          ShowMessage(IntToStr(Length(ACodes)));
        end
      );
    end;
    

    编译它时会产生以下结果 E2555 错误:

    [Dcc32错误] UNIT1。pas(38):E2555无法捕获符号“ACodes”

    我试着只用一个来做同样的事情 Integer 值,并且编译时没有错误。

    procedure Test(ACode : Integer);
    begin
      SubTest(
        procedure()
        begin
          ShowMessage(IntToStr(ACode));
        end
      );
    end;
    

    因此,问题似乎只与开放数组参数有关。

    为什么会发生这种情况,如何避免?

    0 回复  |  直到 4 年前
        1
  •  4
  •   Remy Lebeau    4 年前

    开放数组实际上实现为两个参数,第一个是指向第一个元素的指针,第二个是最高索引。

    知道了这一点,就很清楚为什么这样的东西不能被捕获,因为捕获的价值可能会超过最初的生命周期。

    是的,您可以捕获由于被捕获而可能超过其生命周期的其他东西,但在这些情况下,这是因为您明确地销毁了一个对象,或者释放了一些内存,但不是因为它是如何传递给某个例程的。捕获始终确保该值至少在闭包有效的时间内保持有效。

    闭包中捕获的值在内部实现为编译器创建的闭包支持对象中的字段,因此基本上有一个从捕获的值到这些字段的赋值(简单地说)。开放数组参数不能分配给局部变量或类似变量,只能像数组一样访问,或进一步传递。

        2
  •  2
  •   The Bitman    4 年前

    你的匿名类型声明是错误的。您应该向接受此参数类型的过程声明此类型。比如我的例子 TFoo .它正在发挥作用:

    单位1。考绩制度:

    unit Unit3;
    
    interface
    
    uses
      Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
      Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
    
    type
      TFoo = reference to procedure ( ints_ : array of integer );
    
      TForm3 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
        fFoo : TFoo;
      public
        { Public declarations }
      end;
    
    var
      Form3: TForm3;
    
    implementation
    
    {$R *.dfm}
    
    procedure fooCaller( foo_ : TFoo );
    begin
      foo_( [1,2,3] );
    end;
    
    procedure fooCaller2( foo_ : TFoo; ints_ : array of integer );
    begin
      foo_( ints_ );
    end;
    
    procedure TForm3.Button1Click(Sender: TObject);
    begin
      fooCaller(
        procedure ( ints_ : array of integer )
        var
          i : integer;
        begin
          i := length( ints_ );
        end );
    
      // OR  
    
      fooCaller2(
        procedure ( ints_ : array of integer )
        var
          i : integer;
        begin
          i := length( ints_ );
        end, [1,2,3] );
    end;
    
    end.
    

    单位1。dfm:

    object Form3: TForm3
      Left = 0
      Top = 0
      Caption = 'Form3'
      ClientHeight = 411
      ClientWidth = 852
      Color = clBtnFace
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'Tahoma'
      Font.Style = []
      OldCreateOrder = False
      PixelsPerInch = 96
      TextHeight = 13
      object Button1: TButton
        Left = 288
        Top = 72
        Width = 75
        Height = 25
        Caption = 'Button1'
        TabOrder = 0
        OnClick = Button1Click
      end
    end