Delphi:无法分配“for in”中使用的变量!

Delphi:无法分配“for in”中使用的变量!,delphi,delphi-2010,Delphi,Delphi 2010,为什么编译器不允许for…in循环中的赋值 procedure TForm1.Button1Click(Sender: TObject); Var ars : Array [0..10] of Integer; s : Integer; ct : Integer; begin ct := 0; for s in ars do Begin s := ct; // Does not compile! Inc(ct); End; End; 我对德尔福一无所

为什么编译器不允许for…in循环中的赋值

procedure TForm1.Button1Click(Sender: TObject);
Var
  ars : Array [0..10] of Integer;
  s : Integer;
  ct : Integer;
begin
  ct := 0;
  for s in ars do
  Begin
    s := ct; // Does not compile!
    Inc(ct);
  End;
End;

我对德尔福一无所知。但是,大多数语言不允许在foreach中指定迭代变量。为什么要这样做?

只需使用while循环即可

procedure TForm1.Button1Click(Sender: TObject);
Var
  ars : Array [0..10] of Integer;
  i : Integer;
  ct : Integer;
begin
  ct := 0;
  i := 0;
  while i < Length(ars) do
  Begin
    ars[i] := Ct; //Does Compile!
    Inc(ct);
    inc(i);
  End;
End;

这是不受支持的,就像在普通for循环中,即使是简单的循环迭代器变量也不能修改一样。即使这在for-in中得到了支持,在这种情况下也没有多大意义

整数是值类型,因此在循环的每次迭代中,所要实现的就是将s初始化为数组中某个元素的值,然后由Ct覆盖s

但是数组内容不会被修改,代码的净效果也不会改变

要从for-in中获得您期望的结果,您必须能够使用合适的引用类型(在本例中是指向整数的PInteger指针)进行迭代,从而生成对数组元素的引用,而不是这些元素的值的副本。然后可以使用取消引用的指针为每个元素指定一个新值:

var
  ars : array [0..10] of Integer;
  s : PInteger;
  ct : Integer;
begin
  ct := 0;
  for s in ars do  // << this WON'T yield pointers to the array elements ..
  begin
    s^ := Ct;      // .. but if it did you could then write this
    Inc(ct);
  end;
end;

但不要激动——这也行不通,它只是说明了问题的本质,问题源于参考值与值之间的差异。

为了更好地理解这一点,我想说,理解s是由中的for s控制的。。。。构造,也就是说,当s控制for循环时,几乎任何语言编写良好的编译器都会阻止您这样做。任何编写得不够好而无法阻止此操作的编译器,都应该使用编译器警告或lint工具进行备份,这些警告或工具指示您正在做的事情最好是非常糟糕的风格,最坏的情况下,可能会导致一些难以预测的未定义行为。如果将s设置为高于长度的值,会发生什么情况?循环应该中止还是继续?

变量S只是数组中值的副本,因此更改它没有意义。构造

for s in ars do
基本相当于

for i := low(ars) to high(ars) do
  s := ars[i]
所以给s赋值没有意义。这样做循环

procedure TForm1.Button1Click(Sender: TObject);
Var
  ars : Array [0..10] of Integer;
  i : Integer;
  ct : Integer;
begin
  ct := 0;
  for i := low(ars) to high(ars) do
  Begin
    ars[i] := ct;
    Inc(ct);
  End;
End;

您的脚本中有一个输入错误:您声明了ct小写,但您是从ct大写赋值的。确保这不是您看到的错误的原因。Delphi 2010是否区分大小写?早期版本不适用t@JamesB,这是我对一种我并不懂的语言发表评论的结果。詹姆斯是对的。阿菲克·帕斯卡从来都不区分大小写。那么,你的问题是什么,西尔文?德尔福也是这样。我知道这是不允许的,但给定的用例是完全有效的。@Uwe-用例根本不有效,因为它可能希望实现海报所要求的,至少在Delphi中类型系统的性质没有根本改变的情况下是这样。即使编写的代码被允许编译,这也是不可操作的。其效果将是更改临时变量的值,而不是修改正在迭代的集合的内容,因为发布的代码没有明显的目的。正如我所说的,我知道不允许更改迭代器变量,但用例可能是:迭代元素数组并将每个元素设置为固定值。在本例中,数组索引的类型一点也不困扰我,所以for-In循环看起来非常有吸引力。您必须知道,在for-in循环中,循环变量是只读的,或者是对应数组元素的副本,以确保这不起作用。查看VCL中的一些枚举数可以让您了解这一点。为什么您更喜欢while循环而不是简单的for i:=0 to Lengthars-1 do循环?问题不在于for循环,而在于for in循环。@Rob Kennedy我最初发布这篇文章时没有问题。@Uwe Raabe取决于他们想对循环做什么,因为你也不能为循环变量赋值。如果没有更具体的上下文,while循环会更灵活。@James,我看不出这是一种防御。当你自己承认没有什么可回答的时候,你怎么可能发布有用的答案?@Rob Kennedy我只是假设他的问题是,我该如何处理编译过的代码,就像通常情况下使用这个不编译的代码发布的情况一样。我想你把这个循环与普通的Delphi for循环混淆了。它是for-in循环,其中s是数组中的值,而不是索引。如果它是一个索引,我们可能会试图将s设置为一个大值,以使循环停止运行,但是在这里,很明显Sylvain想要更改存储在数组中的值,就好像s是引用或别名,而不是它的副本。在普通的delphi for循环中,您可以正确地更改它吗?但那仍然是非常糟糕的风格。我希望代码度量或LINT工具至少能向我指出这一事实。不,您不能在任何for循环中更改循环变量。我的观点是
因此,即使允许在此循环中为s赋值,也不会对循环的运行方式产生任何影响,因为它实际上不会以任何方式控制循环。事实上,我有一个记录数组,我想用一个特定的值初始化每个元素。