16、元素可变的情况下不应该使用数组
废话
而且使用数组时不能指定过大的长度,这会使回收时效率特别低。当内存超过85KB时,就是数组的长度过长了
17、多数情况下使用foreach进行循环遍历
foreach用到了迭代器,下面是手动实现的简单迭代器
interface IMyEnumerator
{
bool MoveNext();
object Current { get; }
}
interface IMyEnumerable
{
IMyEnumerator GetEnumerator();
int Count { get; }
}
class MyList : IMyEnumerable
{
object[] items = new object[10];
IMyEnumerator myEnumerator;
public object this[int i]
{
get { return items[i]; }
set { items[i] = value; }
}
public int Count
{
get { return items.Length; }
}
public IMyEnumerator GetEnumerator()
{
if (myEnumerator == null)
myEnumerator = new MyEnumerator(this);
return myEnumerator;
}
}
class MyEnumerator : IMyEnumerator
{
int index = 0;
MyList myList;
public MyEnumerator(MyList myList)
{
this.myList = myList;
}
public bool MoveNext()
{
if(index +1 > myList.Count)
{
index = 1;
return false;
}
else
{
index++;
return true;
}
}
public object Current
{
get { return myList[index - 1]; }
}
}
下面是使用系统的 IEnumerator IEnumerable ICollection继承自IEnumerable
ICollection<int> list = new List<int>();
list.Add(4);
list.Add(5);
list.Add(2);
list.Add(6);
IEnumerator<int> enumerator = list.GetEnumerator();
while (enumerator.MoveNext())
{
Console.WriteLine(enumerator.Current);
}
这个是foreach的反编译代码
可以看出跟上面我们自己实现的基本一致,但是多了一个自动调用Dispose()
18、foreach不能代替for
在foreach中不能更改集合的内容,因为IEnumerator 内部维护了一个版本号,就上面一段代码来分析
如果我们在已经创建过的IEnumerator后面再修改list的内容,然后使用IEnumerator,list的版本号就会跟IEnumerator里面维护的版本号不同,系统就会报错,下面是IEnumerator的MoveNext() 实现,可以看到IEnumerator里面维护着一个数组,并且每次调用时都会判断版本号是否相同
但是for循环不会产生这种情况,for只是简单的索引取值
19、使用有效的对象和集合初始化
对象初始化:
Person p1 = new Peroson() { Name = "Rose" , Age = 21 };
集合初始化
List<Person> lists = new List<Person>()
{
new Person(){Name = "Rose",Age = 22},
new Person(){Name = "Jack",Age = 21},
new Person(){Name = "Ju",Age = 22}
};
不过初始化的设定绝不仅仅是为了对象和集合初始化的方便,它更重要的作用是为LINQ查询中的匿名类型进行属性的初始化。由于LINQ查询返回的集合中匿名类型的属性都是只读的,如果需要为匿名类型属性赋值,或者增加属性,只能通过初始化设定项来进行
List<Person> lists = new List<Person>()
{
new Person(){Name = "Rose",Age = 22},
new Person(){Name = "Jack",Age = 21},
new Person(){Name = "Ju",Age = 22}
};
//通过计算age的大小来获得新的属性AgeScope 并存入到一个匿名类型中
var temp = from p in lists select new { p.Name, AgeScope = p.Age > 21 ? "Old" : "Young" };
foreach (var item in temp)
{
Console.WriteLine(item.Name + ":" + item.AgeScope);
}
20、使用泛型集合代替非泛型集合
主要就是使用List<T> 代替ArrayList
ArrayList 不仅需要装箱拆箱,而且编译器并不会检查类型