- 注册时间
- 2004-8-30
- 最后登录
- 1970-1-1
|
本文原出自Danny Thorpe的BLOG,可以点击这里查看原文,本人的E文一般,翻译的自然也马马虎虎,建议好学者阅读原文以获取正确的认知。
在Delphi的下一个发行版本中,编译器将会支持一种新的循环语法:”for .. in”,”for .. in”运行起来类似于经常使用的for循环,特别之处在于,你并不需要自己指定一个用于循环的索引变量。如果你想处理一个群集对象中所有的字符串,你只需要说:这就是个那个群集,我想得到里面的每一个字符串,开始吧!
下面是语句的表达式:
for <variable> in <container expression> do <statement>;
variable是一个本地变量名,他的类型必须是容器所包含数据的类型。
Container 是表达式,他必须符合以下特征中的一种。
实现了IEnumerable接口。
实现了Delphi编译器所认可的Enumerator模式。
Delphi编译器所认可的数据容器。
而statement,如果你不知道他所指的意思,那么你现在肯定已经昏昏欲睡了。
范例:
type
TStringArray = array of String;
procedure Demo1(const List: TStringArray);
var
S: String;
begin
for S in List do
writeln(S);
end;
上面的代码可以把参数中指定的字符串数组所包含的全部字符串进行输出处理,需要注意的是,你并不需要声明一个本地变量并且使用他来指向数组中的每个元素,编译器会在幕后为你打理这些。
procedure Demo2(List: System.Collections.Specialized.StringCollection);
var
S: String;
begin
for S in List do
writeln(S);
end;
Demo2过程实际上所作的和DEMO1非常类似,区别在于他不是输出字符串数组中的字符串,而是输出了.NET StringCollection对象。编译器会查看StringCollection类是否实现了Enumerator模式(含有公开方法GetEnumerator以及一些其他细节)或者是否实现了IEnumerable接口,之后产生的机器码,可以通过enemerator接口来获得群集中每个数据。
这样的好处是,你不需要关心如何得到所有数据的细节,你只需要关心群集中数据的类型以及你想对他们作些什么。
大概你现在已经领会到,这个for..in语句在其他语言里面已经得到了广泛的使用。但是,我们仍然把容器表达式(container expression)限制为实现接口或者enumerator模式的对象实例。Delphi for..in语句同样支持了一些delphi编译器所知的包含有不同元素的数据类型:arrays(数组元素),strings(字符串),以及set(枚举)。
下面是一个使用set的例子:
type
TRole = (worker, manager, executioner, CEO);
TJobRoles = set of TRole;
procedure Demo3(const JobRoles: TJobRoles);
var
R: TRole;
begin
for R in JobRoles do
// use R here;
end;
在Demo3中的循环代码中,可以得到集合变量JobRoles中的所有R可以获得的数值。他相当于一个枚举所有可用数值的循环语句(for x := Low(TRole) to High(TRole) do),并且测试JobRoles中的所有数据。
For..in同样可以处理多维数组:
type
TMultiArray = array [0..10, 0..3, 0..9] of Integer;
procedure DemoMulti(const table: TMultiArray);
var
X: Integer;
begin
for X in table do
writeln(x);
end;
DemoMulti可以获取TMultiArray数组中全部的440个单元,顺序则是最右面的索引优先。也就是说首先是表[0,0,0],然后表[0,0,1],之后表[0,0,2]……。这有些相当于编写3个严谨并使用私有循环索引的循环语句。但是谁真正关心呢?你只需要关心你想对每个项目所做的事情就好了,剩下的琐事就由编译器来为你处理。
为什么是For..in?为什么不是Foreach/For Each/ForEver?
理由是,这并不是必要的,For..In语句可以在不增加额外的保留字的情况下正确的被分析和与其他循环语句区别开来,为什么我们要把事情做的更加复杂呢?
将来的设想
在数据库类中实现enumerator模式或接口。 For DataRow in SqlQuery do..
用于进行文件搜索的类。 For FileName in FileSearch(*.pas) do…
For EmailAddress in OutlookAddressBook do Spam.a.Matic(…)
另:这个for..in语句并不仅限于.NET平台,Delphi编译器同样可以生成在Win32下使用的代码。
|
|