关于c#中集合的疑问与部分想法(一)(欢迎拍砖和建议)
2013-05-10 19:54
295 查看
一、关于集合遍历的模式,本人目前所知的有两种,一种是length-index模式,一种是interator模式,前一种在应用在数组中,另一种则在泛型集合中广为应用,这也是IEnumerator<T>的设定模式,为了在同时遍历一个集合(多线程,内嵌遍历)的情况下,能正确获取当前值,因此泛型集合继承的接口为IEnumerable<T>,其规范是返回 GetEnumerator(),这样在同时遍历一个集合时,获得的是不同的IEnumertor<T>对象,这样就相当于在同时查阅一本书,但可以按照不同的书签(IEnumerator)来查。
疑问:(1)除了这两种模式是否还有其他的模式,其相通之处?
(2)对于数组而言,因其length-index模式,其foreach语法下和for循环下,编译器生成的CIL代码一致,所以其效率也应当一致?
(3)还有那个基于Duck—Typing的法则,对于foreach的支持,不一定非得继承IEnumerable<T>,也可以实现MoveNext() Current()即可;
(4)对于Stack<T> ,Queue<T>,dictionary<Tkey,TElement>中,无法进行索引访问的,怎么MoveNext() ,怎么获取Current值?如果内部采取List等含索引访问的对象,那最终不还是Length-index模式?
二、关于集合中IEnumerable<T>的扩展,正是因为有了泛型,有了接口扩展,才会有这么强大的linq语法支持,(Ps:接口扩展,基于对已声明的类,可以再类外再自定义该类的实例方法 语法(eg.):void FunctionMethod(this Class1 c1,object object1); 其中Class1 即指需要进行扩展的类,甚至可以是接口,而对于接口的扩展方法,其所有继承该接口的子类均可以使用,,,本人觉得这个真的是修改和升级的强大工具啊,,,木有它,就木有linq)。
其中关于linq语法中,有一个相当重要而易忽略的特性,即推迟执行,,:所谓推迟执行,即指在System.linq.Enumerable类中各种查询函数里面所传递的委托实例,即lambada表达式,lambada表达式,并不会在调用该查询函数时执行,而是只有在遍历是才会执行,如:Select<TSource, TResult>(IEnumerable<TSource>, Func<TSource, TResult>),其中Func<TSource, TResult>的实例,并不会在调用Select函数时执行,
而是在遍历TSource时,才执行,而且会在每次遍历时执行,稍不注意就极大地影响性能;
示例代码如下:
以上结果均经过网上编译器编译实现;http://www.compileonline.com/compile_csharp_online.php
为解决每次遍历都会重新执行查询表达式,因此一般是给个缓存,如 var items=items.ToArray();即在下次执行对items的遍历时,查询条件不会再次执行;
疑问:
(5)推迟执行的内部实现是怎么回事,,,?按说Select函数会有对Func(Parameter1)的调用,那么怎么会延迟了?
疑问:(1)除了这两种模式是否还有其他的模式,其相通之处?
(2)对于数组而言,因其length-index模式,其foreach语法下和for循环下,编译器生成的CIL代码一致,所以其效率也应当一致?
(3)还有那个基于Duck—Typing的法则,对于foreach的支持,不一定非得继承IEnumerable<T>,也可以实现MoveNext() Current()即可;
(4)对于Stack<T> ,Queue<T>,dictionary<Tkey,TElement>中,无法进行索引访问的,怎么MoveNext() ,怎么获取Current值?如果内部采取List等含索引访问的对象,那最终不还是Length-index模式?
二、关于集合中IEnumerable<T>的扩展,正是因为有了泛型,有了接口扩展,才会有这么强大的linq语法支持,(Ps:接口扩展,基于对已声明的类,可以再类外再自定义该类的实例方法 语法(eg.):void FunctionMethod(this Class1 c1,object object1); 其中Class1 即指需要进行扩展的类,甚至可以是接口,而对于接口的扩展方法,其所有继承该接口的子类均可以使用,,,本人觉得这个真的是修改和升级的强大工具啊,,,木有它,就木有linq)。
其中关于linq语法中,有一个相当重要而易忽略的特性,即推迟执行,,:所谓推迟执行,即指在System.linq.Enumerable类中各种查询函数里面所传递的委托实例,即lambada表达式,lambada表达式,并不会在调用该查询函数时执行,而是只有在遍历是才会执行,如:Select<TSource, TResult>(IEnumerable<TSource>, Func<TSource, TResult>),其中Func<TSource, TResult>的实例,并不会在调用Select函数时执行,
而是在遍历TSource时,才执行,而且会在每次遍历时执行,稍不注意就极大地影响性能;
示例代码如下:
using System.Collections; using System.Linq; using System; class Program { static void Main() { var employees=new[] { new {Name="liSan",Age="30"}, new {Name="WangSi",Age="41"} }; var items=employees.Select(employee=>{ Console.WriteLine("TestMark1"); return employee.ToString();} ); Console.WriteLine("TestMark2"); foreach(var item in items) { Console.WriteLine(item); } Console.WriteLine(items.Count()); } } //Output: TestMark2 TestMark1 {Name=liSan,Age=30} TestMark1 {Name=WangSi,Age=41} TestMark1 TestMark1 2
以上结果均经过网上编译器编译实现;http://www.compileonline.com/compile_csharp_online.php
为解决每次遍历都会重新执行查询表达式,因此一般是给个缓存,如 var items=items.ToArray();即在下次执行对items的遍历时,查询条件不会再次执行;
疑问:
(5)推迟执行的内部实现是怎么回事,,,?按说Select函数会有对Func(Parameter1)的调用,那么怎么会延迟了?
相关文章推荐
- 关于C#集合想法与疑问(二)---自定义集合 C#二叉树实现
- 关于C#调用非托管动态库方式的性能疑问
- c#的as类型转换详细理解,欢迎园友拍砖。
- 关于c# 泛型List集合对象的用法及相关操作
- C#中关于集合的一个小例子
- C#中关于静态与非静态的一个疑问
- 关于对《Windows Mobile平台应用与开发》一书中部分内容的疑问
- C# asp.net 中关于配置文件的配置和作用(数据库部分)
- 关于C#中非可空类型的一点建议
- 主题:关于REST的一点想法,欢迎大家讨论。
- 一道趣味数学题 c# 版 欢迎拍砖
- 收集关于录音录成mp3的思路,欢迎参考和建议
- C++ STL 有关于SET集合部分 的自定义数据类型的排序 以及 pair的使用
- 编写高质量代码改善C#程序的157个建议——建议21:选择正确的集合
- 编写高质量代码改善C#程序的157个建议——建议25:谨慎集合属性的可写操作
- 改善C#程序的建议3:在C#中选择正确的集合进行编码
- 关于斯诺登暴料部分卡商SIM卡密钥被窃取的几点想法
- 关于缓存的一点思考。欢迎拍砖!