Delphi之For In

Java和C#里面的For In用起来真爽,我们Delphin也不用眼红了,从D2005起,Delphi里面也有这个功能了.


首先我们要知道哪些类型可以用For In吧,下面就是:

  • for Element in ArrayExpr do Stmt; 数组
  • for Element in StringExpr do Stmt; 字符串
  • for Element in SetExpr do Stmt; 集合
  • for Element in CollectionExpr do Stmt; 集合
  • for Element in Record do Stmt; 结构体

我们来看例子:

view source

?
01type
02THuangJacky = (hjA,hjB,hjC,hjD);
03TJackyHuang =record
04a,b,c:Integer;
05end;
06const
07stringExpr='HuangJacky';
08arrayExpr:array[0..5]ofInteger= (1,2,3,4,5,6);
09setExpr:setofTHuangJacky = [hjA,hjB,hjD];
10procedureTForm1.FormCreate(Sender: TObject);
11var
12I:Integer;
13C:Char;
14D:THuangJacky;
15F:TComponent;
16begin
17forcinstringExprdo
18ShowMessage(C);
19foriinarrayExprdo
20ShowMessage(IntToStr(i));
21fordinsetExprdo
22ShowMessage(IntToStr(Ord(d)));
23forFinSelfdo
24ShowMessage(f.Name);
25end;

是不是很爽呀?哈哈,Delphi也与时俱进呀.

之前写了类助手文章中,老赵问是不是扩展方法,因为对C#没有了解到这么多,所以不知道.

那么我们在Java中要For In必须实现Iterator吧.

那么Delphi的会不会也要呢?

是的,如果我们要自己的类支持For In的话,就必须满足下面的条件:

1 必须有个公共方法GetEnumerator(),这个方法返回值是一个类,接口或者记录体.

2 上面返回的类,接口或者记录体中又必须有公共方法MoveNext(),这个方法的返回值是Boolean.

3 1中返回的类,接口或者记录体中必须有一个只读的属性Current,类型要和集合中的元素一样.

说了这么多,看个例子:

view source

?
01type
02TMyIntArray =arrayofInteger;
03
04TMyEnumerator =class
05Values: TMyIntArray;
06Index:Integer;
07public
08constructorCreate;
09functionGetCurrent:Integer;
10functionMoveNext:Boolean;
11propertyCurrent:Integerread GetCurrent;
12end;
13
14TMyContainer =class
15public
16functionGetEnumerator: TMyEnumerator;
17end;
18
19constructorTMyEnumerator.Create;
20begin
21inheritedCreate;
22Values := TMyIntArray.Create(100,200,300);
23Index := -1;
24end;
25
26functionTMyEnumerator.MoveNext:Boolean;
27begin
28ifIndex < High(Values)then
29begin
30Inc(Index);
31Result :=True;
32end
33else
34Result :=False;
35end;
36
37functionTMyEnumerator.GetCurrent:Integer;
38begin
39Result := Values[Index];
40end;
41
42functionTMyContainer.GetEnumerator: TMyEnumerator;
43begin
44Result := TMyEnumerator.Create;
45end;
46
47var
48MyContainer: TMyContainer;
49I:Integer;
50
51Counter:Integer;
52
53begin
54MyContainer := TMyContainer.Create;
55
56Counter :=0;
57forIinMyContainerdo
58Inc(Counter, I);
59
60WriteLn('Counter = ', Counter);
61end.