一直想写一系列如何提高Performance和Scalability的文章,把我的相关经验和所知道的相关的技巧同大家分享。前一阵在园子里有一篇讨论for each 和 for两种循环那个具有更好的performance的blog,议论得沸沸扬扬。我觉得这是一个很好的切入点,我就已此作为引子,开始我的这个系列的文章。这篇文章的重点不是在于比较这两种循环孰优孰劣,我将讨论的重点是如何更好地定义Collection,如何在判断在什么时候该用Array,什么时候用Collection。
一、for each的本质
我们知道,所有实现了System.Collections. IEnumerable接口的类,我们都可以对它运用for each loop。为了弄清楚它的执行过程,我先给出一个Sample:
using
System;
using
System.Collections.Generic;
using
System.Text;
using
System.Collections;
namespace
Artech.CustomCollection
{
structEmployee

{
PrivateFields#regionPrivateFields
privatestring_employeeID;
privatestring_name;
privateint_age;
#endregion

Constructor#regionConstructor
publicEmployee(stringemployeeID,stringname,intage)

{
this._employeeID=employeeID;
this._name=name;
this._age=age;
}
#endregion

PublicProperties#regionPublicProperties
publicstringEmployeeID

{
get
{return_employeeID;}
set
{_employeeID=value;}
}
publicstringName

{
get
{return_name;}
set
{_name=value;}
}
publicintAge

{
get
{return_age;}
set
{_age=value;}
}
#endregion

Tostring#regionTostring
publicoverridestringToString()

{
returnstring.Format("\tID:\t{0}\n\tName:\t{1}\n\tAge:\t{2}\n\t",this._employeeID,this._name,this._age);
}
#endregion
}
classEmployeeList:IEnumerable

{
privateEmployee[]_employees;
publicEmployee[]Employees

{
get
{return_employees;}
set
{_employees=value;}
}

IEnumerableMembers#regionIEnumerableMembers
publicvirtualIEnumeratorGetEnumerator()

{
Console.WriteLine("EmployeeList.GetEnumerator()isinvoked");
returnnewGenericEmployeeEnumerator(this._employees);
}
#endregion
}
classEmployeeEnumerator:IEnumerator

{
privateEmployee[]_employees;
privateint_index=-1;
publicEmployeeEnumerator(Employee[]employees)

{
this._employees=employees;
}

IEnumeratorMembers#regionIEnumeratorMembers
publicobjectCurrent

{
get

{
Console.WriteLine("EmployeeEnumerator.Currentisinvoked");
returnthis._employees[this._index];
}
}
publicboolMoveNext()

{
Console.WriteLine("EmployeeEnumerator.MoveNextisinvoked");
if(this._index<this._employees.Length-1)

{
this._index++;
returntrue;
}
returnfalse;
}
publicvoidReset()

{
this._index=-1;
}
#endregion
}
classProgram

{
staticvoidMain(string[]args)

{
Employee[]employees=newEmployee[]
{newEmployee("0001","ZhangSan",21),newEmployee("0002","LiSi",30)};
EmployeeListempoyeeList=newEmployeeList();
empoyeeList.Employees=employees;
Console.WriteLine("Beginforeachloop
");
foreach(EmployeeemployeeinempoyeeList)

{
Console.WriteLine(employee.ToString());
}
Console.WriteLine("\n\nBeginwhileloop
");
IEnumeratorenumerator=empoyeeList.GetEnumerator();
while(enumerator.MoveNext())

{
Employeeemployee=(Employee)enumerator.Current;
Console.WriteLine(employee.ToString());
}
}
}
}
我们先运行一下上面的程序再来讲述具体的执行的流程。

在上面的Sample中我们先定义了一个Employee的struct,之所以使用struct而不用一般的class,我将在后面的部分介绍。
struct
Employee
{
PrivateFields#regionPrivateFields
privatestring_employeeID;
privatestring_name;
privateint_age;
#endregion

Constructor#regionConstructor
publicEmployee(stringemployeeID,stringname,intage)

{
this._employeeID=employeeID;
this._name=name;
this._age=age;
}
#endregion

PublicProperties#regionPublicProperties
publicstringEmployeeID

{
get
{return_employeeID;}
set
{_employeeID=value;}
}
publicstringName

{
get
{return_name;}
set
{_name=value;}
}
publicintAge

{
get
{return_age;}
set
{_age=value;}
}
#endregion

Tostring#regionTostring
publicoverridestringToString()

{
returnstring.Format("\tID:\t{0}\n\tName:\t{1}\n\tAge:\t{2}\n\t",this._employeeID,this._name,this._age);
}
#endregion
}
然后我们基于这个Emplyee struct,定义了与之对应的Collection:EmplyeeList。EmplyeeList实现了System.Collections. IEnumerable接口。并以一个virtual 方法的形式实现了该接口的GetEnumerator方法。(为什么用virtual方法的原因,我会再后续部分解释)。
Public
virtual
IEnumeratorGetEnumerator()
本文探讨了如何通过合理选择数组或集合来提高程序性能和可扩展性,并深入解析了foreach循环的本质及其在不同场景下的应用。

1502

被折叠的 条评论
为什么被折叠?



