一、概述:
软件开发过程中不可避免会用到集合,C#中的集合表现在数组和若干集合类。不管是数组还是集合类都有若干优点。这样如何使用集合是我们开发过程中不可或缺的技巧。
二、C#中集合介绍:
在上图中可以看见C#集合分类:
集合分为线性和非线性(很少用),这里我们终点介绍线性集合。
1. 如果集合的数目固定并且不涉及转型,使用数组效率高,否则就是用List<T>。
2. 栈满足先进后出原则,队列满足先进先出。
3. 数据字典:存储的是键值对,值基于键的散列码的基础进行存储。字典对象包含集合元素存储桶组成,每一个存储桶与基于该元素的键的哈希值关联。
4. 双向链表:当我们觉得集合中插入和删除数据速度慢的时候就可以考虑双向链表。
三、C#中集合使用:
1.元素数量可变的情况下不应该使用数组:存在装箱和开辟空间
2. 多数情况使用foreach进行循环遍历:
1)foreach提供了简单的迭代器语法。
2)自动将代码置入try-finally块。
3)若类型实现了Dispose接口,它循环结束后自动调用Dispose方法。
3. froeach不能代替for:froeach只支持迭代不支持对集合进行增删操作。
4. 尽量使用泛型集合代替非泛型集合:可以记录避免装箱和拆箱操作。
5. 确保集合线程安全:建议使用线程锁
static List<Person> list = new List<Person>() { new Person(){Name="Abel",Age=26}, new Person(){Name="Topmson",Age=26}, new Person(){Name="Erwin",Age=27}, new Person(){Name="Lucy",Age=20} }; static AutoResetEvent autoset = new AutoResetEvent(false); static object sycObj = new object(); static void Main(string[] args) { Thread t1 = new Thread(() => { autoset.WaitOne();//保证t2运行后在运行此段代码 lock (sycObj) { foreach (Person item in list) { Console.WriteLine("姓名" + item.Name); Thread.Sleep(1000); } } }); t1.Start(); Thread t2 = new Thread(() => { //通知t1可以执行代码 autoset.Set(); Thread.Sleep(1000);//确保删除操作在迭代过程中 lock (sycObj) { list.RemoveAt(2); Console.WriteLine("删除成功!"); } }); t2.Start(); Console.ReadKey(); } class Person { public string Name { get; set; } public int Age { get; set; } }
6.查询List<T>使用Lambda表达式并使用匿名类型存储Linq查询结果:
public class LinqToList { private List<People> peopleList=new List<People>(); public static LinqToList getInstance() { return new LinqToList(); } public void setPeopleList() { peopleList.Add(new People() { Name = "王艳丽", Age = 12, Sex = "男" }); peopleList.Add(new People() { Name = "王小花", Age = 18, Sex = "女" }); peopleList.Add(new People() { Name = "张三", Age = 22, Sex = "男" }); peopleList.Add(new People() { Name = "莉莉丝", Age = 50, Sex = "女" }); peopleList.Add(new People() { Name = "赵云", Age = 34, Sex = "男" }); peopleList.Add(new People() { Name = "王二麻子", Age = 66, Sex = "女" }); peopleList.Add(new People() { Name = "李四", Age = 24, Sex = "男" }); peopleList.Add(new People() { Name = "小命", Age = 19, Sex = "女" }); } public List<People> getPeopleList() { List<People> list=new List<People>(); //var query = from people in this.peopleList // where people.Name.Length == 3 && // people.Name.StartsWith("王") // select people; var query = this.peopleList.Where(P => P.Name.Length == 3 && P.Name.StartsWith("王"));
foreach (var item in query) { list.Add(item); } return list; } }
7.理解延迟求值和主动求值之间的区别:
List<int> list = new List<int>() { 0, 1, 2, 3, 4, 5,6,7,8,9 }; var lazy = list.Where(L => L > 5); var eager = list.Where(L => L > 5).ToList<int>(); list[0] = 10; Console.WriteLine("lazy:"); foreach (var item in lazy) { Console.WriteLine("{0};", item); } Console.WriteLine("eager:"); foreach (var item in eager) { Console.WriteLine("{0};", item); } Console.ReadKey();
输出:
lazy:10;6;7;8;9;
eager:6;7;8;9;
对查询调用ToList,ToArray等方法,将会使其立即执行查询,不会等在迭代的时候执行查询。
8. 区别LINQ查询中的IEnumerable<T>和IQueryable<T>
LINQ查询方法一共提供了两类扩展方法,在System.Linq命名空间下有两个静态类:
Enumerable类它针对继承了IEnumerable<T>接口的集合类进行扩展;用于本地数据源查询。
Queryable类它针对继承了IQueryable<T>接口的集合类进行扩展;用于远程数据源查询。
9.使用LINQ取代集合中的比较器和迭代器:想想SQL就能理解,他们不需要这些。
10.在LINQ查询中避免不必要的迭代:
例如:返回年龄等于20的一个元素即可:
方法一:from c in list where c.Age==20 Select c
方法二:(from c in list where c.Age==20 Select c).First()