在foreach的判断条件里执行方法会有效率问题吗?
楼猪平时一有空就有看别人代码的习惯,从许多优秀规范的代码中学习到了很多简约高效的写法和画龙点睛的思想精华。但是有的时候也会觉得某些写法很值得玩味。比如刚看到一段代码,在foreach的条件判断里加了一个方法。楼猪一开始想当然地认为循环几次,方法也会执行几次,这样肯定会有效率问题。但是看来看去还是不确定写代码的人为什么要这么写,难道当时他不小心没有注意到这个问题,抑或他rp正处低谷,抑或是他一时不负责任无缘无故就爱咋咋地了?!
毛主席教导我们“没有调查就没有发言权”;我D强调全社会要树立科学发展观。认识到问题的严重性,所以楼猪又在本地测试了一下:
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CSStudy
{
class Program
{
private static int executeTimes = 0;
static void Main(string[] args)
{
foreach (string item in CreateStrArr())//这里调用CreateStrArr方法,CreateStrArr会执行多次吗?
{
Console.WriteLine(item);
}
Console.WriteLine("As you see,method CreateStrArr execute times:{0}", executeTimes);
Console.ReadKey();
}
static List<string> CreateStrArr()
{
executeTimes++;//记录CreateStrArr方法到底跑了几遍
List<string> listResults = new List<string>();
for (int i = 0; i < 5; i++)
{
listResults.Add((i + 1).ToString());
}
return listResults;
}
}
}
测试结果印证了这个世界“不会有无缘无故的恨,当然也不会有无缘无故的爱”。正如测试结果显示的那样,CreateStrArr方法只跑了一遍,静态方法CreateStrArr改成实例方法,效果一样(原谅NC楼猪心里阴暗,本来是铁了心要看笑话的...),应该不会有效率问题,那个写代码的人可以笑了。
失落的楼猪又查了一遍msdn,“foreach 语句为数组或对象集合中的每个元素重复一个嵌入语句组。foreach 语句用于循环访问集合以获取所需信息,但不应用于更改集合内容以避免产生不可预知的副作用.”,明显没有告诉我们为什么示例中的foreach里的方法只执行一次。又google了一下之后,终于发现原来是编译时,编译器对foreach做了优化。nnd,老以为rp出问题,原来是编译器的魔法,服了。
附:找出表中某个字段的重复值
在之前的iBATIS.net文章里我们提到一个person表:
[PER_ID] [int] IDENTITY(1,1) NOT NULL,
[PER_FIRST_NAME] [nvarchar](40) COLLATE Chinese_PRC_CI_AS NOT NULL,
[PER_Last_NAME] [nvarchar](40) COLLATE Chinese_PRC_CI_AS NOT NULL,
[PER_BIRTH_DATE] [datetime] NULL,
[PER_WEIGHT_KG] [float] NULL,
[PER_HEIGHT_M] [float] NULL,
CONSTRAINT [PK_Person] PRIMARY KEY CLUSTERED
(
[PER_ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
在测试的时候,已经被循环导入了很多重复数据,然后,笔者准备查看一下哪些名字(PER_FIRST_NAME)的记录是重复的。一开始也不知道是哪根筋出了问题,NC楼猪发扬一不怕苦,二不闲累的精神,先尝试用自连接的方式来查询。倒腾若干时间未果后,又秉承一贯坚持不懈认真负责的态度,接着改用临时表查询,继续未果后......我kao,还没到放假过年呢,怎么那么喜庆?在重新确定自己要干什么的时候,欣然发现下面这一句就可以了:
from person
group by PER_FIRST_NAME
having count(PER_FIRST_NAME)>1
太阳啊,这不就是利用SQL的count和分组功能么,怎么一开始会想那么复杂高深呢?要寻找智商上的优越感也太明显了吧?所以,以后我们要找出表中某个字段的重复值,只要一句简单的SQL语句即可(原理就是count+分组):
select 字段名,count(字段名) from 表名 group by 字段名 having count(字段名)>1
什么,您已经乐了?这木有任何技术含量?您找到了自信?!楼猪在此向您表示极度的遗憾。人么,总(允许)有犯傻rz的时候啊。