为什么编译器不允许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;
答案 0 :(得分:8)
这不受支持,就像在“正常”for循环中无法修改简单的循环迭代器变量一样。即使这在 for-in 中得到支持,在这种情况下也没有多大意义。
整数是值类型,因此在循环的每次迭代中,所有可以实现的是 s 将初始化为数组元素的值,然后 s 由 Ct 覆盖。
但是数组内容会不被修改,代码的净效果将是“无变化”。
要获得您对 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;
但是不要激动 - 这也不会起作用,它只是表明问题的本质源于参考与价值的差异。
答案 1 :(得分:5)
我对Delphi一无所知。但是,大多数语言不允许您在foreach
中分配迭代变量。你为什么要这样做?
答案 2 :(得分:2)
只需使用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;
答案 3 :(得分:1)
为了更好地理解这一点,我会说,“理解s是由for s in .... construct”控制的,也就是说,当s控制for循环时,一个编写良好的编译器几乎任何语言都会阻止你这样做。任何编写得不够好的编译器都应该通过编译器警告来备份,或者是一个lint工具,它表明你正在做一些最好的,非常糟糕的风格,最坏的情况可能会导致一些难以预测的“未定义”行为。如果将s设置为高于Length(ars)的值,会发生什么?循环应该中止,还是应该继续?
答案 4 :(得分:1)
变量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;