- 浏览: 462792 次
- 性别:
- 来自: 坚持零分
文章分类
最新评论
-
wzwahl36:
文章非常赞,http://www.atool.org/img2 ...
在浏览器中解析Base64编码图像 -
realyasswl:
ie sucks
IE9 媲美Firebug的强大的程序员开发工具 -
di1984HIT:
不错啊。呵呵。
MS的一些小工具 -
NothingCanBeDone:
楼主,你这Project,能放出来了,感激不尽。
[Ray Linn]用Visual Studio 2008开发IE BHO(浏览器帮助对象) 之三 -
烬难烬:
这就没了???我去....
IE9 媲美Firebug的强大的程序员开发工具
这个系列的主要目的是尽量能覆盖C# 1.1之后的语法更新,以便让大家能够熟悉C# 2.0到4.0的语法特性,以提高编程效率,这里我忽略了一些诸如泛型、LINQ等等需要大章节才能阐述清楚的东西,原因是关注这些知识点的文章比比皆是,我所要写的语法都是一些比较小的,容易被人所忽略的地方。如果我有任何遗漏或者错误的地方,请给我个站内消息
1. 迭代器 适用范围:c# 2.0之后、
C# 1.0开始提供了非常方便的foreach循环,只要一个数据集实现了一个无参数的,返回Enumerator的GetEnumerator方法(甚至不需要实现任何接口),就可以在foreach循环中遍历数据集中的每个元素。大部分情况下,我们将数据存入某个Collection类,利用Collection类的GetEnumerator方法,就可以很方便地使用Foreach循环。
但有些时候我们必须自己去实现Enumerator,比如说打印某年每个月的天数,为了体现OOP的原则,我们的程序逻辑(即对闰年的判断,很高兴C#提供了相关的方法)应该被封装起来。
这段代码较长但不难理解,它相当好地封装了程序逻辑,调用起来也相当简洁优雅:
我们也看到实现Enumerator的过程未免过于复杂,一旦我们需要多个Enumerator来进行逆序,正序,奇偶数序迭代,代码就会相当繁杂。
C# 2.0之后新的yield关键字使得这个过程变得轻松简单。
这就是C# 2.0 中的迭代器,它使您能够方便地在类或结构中支持 foreach 迭代,而不必实现整个 IEnumerable 接口。
迭代器的返回类型必须为 IEnumerable、IEnumerator、IEnumerable<T> 或 IEnumerator<T>。当编译器检测到迭代器时,它将自动生成 IEnumerable 或 IEnumerable<T> 接口的 Current、MoveNext 和 Dispose 方法。
yield 关键字用于指定返回的值。到达 yield return 语句时,会保存当前位置。下次调用迭代器时将从此位置重新开始执行。而yield break则可以中止迭代,下面的代码有助于理解这点。
会依次打印出"New York", "Paris" "London". 有时候迭代器与迭代一起可以产生奇妙的效果,但也会耗费大量的内存。
foreach语句会隐式地调用集合的无参的GetEnumerator方法來得到一個迭代器。一个集合类中只能定义一个这样的无参的GetEnumerator方法,不过我们也可以在类中实现多个迭代器,但每个迭代器都必须像任何类成员一样有唯一的名称。
TopToBottom属性的get访问器只返回this,因为Stack本身就是一个可枚举类型。BottomToTop屬性使用C#迭代器返回了另一个可枚举接口。
实现IEnumerable接口的类看起来非常象一个枚举器工厂类,每次都产生一个独立的IEnumerator类。
上面的代码打印了一个从1到10的乘法表。注意FromTo方法只被调用了一次用来产生实现了IEnumerable接口的变量e。而e.GetEnumerator()被调用了多次(通过foreach语句)來产生多个相同的迭代器。這些迭代器都封裝了FromTo声明中指定的代碼。注意,迭代其代码的时候改变了from参数。但是,迭代器是独立的,因此对于from参数和to参数,每個迭代器有它自己的一份拷贝。
期待中,我只知道他用的是函数指针 c转c#的人
1. 迭代器 适用范围:c# 2.0之后、
C# 1.0开始提供了非常方便的foreach循环,只要一个数据集实现了一个无参数的,返回Enumerator的GetEnumerator方法(甚至不需要实现任何接口),就可以在foreach循环中遍历数据集中的每个元素。大部分情况下,我们将数据存入某个Collection类,利用Collection类的GetEnumerator方法,就可以很方便地使用Foreach循环。
但有些时候我们必须自己去实现Enumerator,比如说打印某年每个月的天数,为了体现OOP的原则,我们的程序逻辑(即对闰年的判断,很高兴C#提供了相关的方法)应该被封装起来。
using System; using System.Collections; namespace SharpDemo{ public class DaysOfTheMonth { public DaysOfTheMonth(int year) { this.year = year; } int year = 1900; public System.Collections.IEnumerator GetEnumerator() { return new DaysOfMonthEnumrator(this.year); } class DaysOfMonthEnumrator : IEnumerator { private int[] days = new int[] { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; public DaysOfMonthEnumrator(int year) { if (DateTime.IsLeapYear(year)) { days[1] = 29; } } private int index = -1; public IEnumerator GetEnumerator() { return this; } public void Reset() { index = -1; } public object Current { get { if (this.index < this.days.Length) { return this.days[this.index]; } else { throw new IndexOutOfRangeException(); } } } public bool MoveNext() { if (this.days.Length == 0) { return false; } else { this.index += 1; if (this.index == this.days.Length) { return false; } else { return true; } } } } } }
这段代码较长但不难理解,它相当好地封装了程序逻辑,调用起来也相当简洁优雅:
DaysOfTheMonth enu = new DaysOfTheMonth(1981); foreach( int days in enu) Console.Out.WriteLine(days);
我们也看到实现Enumerator的过程未免过于复杂,一旦我们需要多个Enumerator来进行逆序,正序,奇偶数序迭代,代码就会相当繁杂。
C# 2.0之后新的yield关键字使得这个过程变得轻松简单。
public class DaysOfMonth { int year = 1900; int[] days = new int[] { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; public DaysOfMonth2(int year) { this.year = year; if (DateTime.IsLeapYear(year)) { days[1] = 29; } } public IEnumerator GetEnumerator() { for (int i = 0; i < this.days.Length; i++) { yield return this.days[i]; } } }
这就是C# 2.0 中的迭代器,它使您能够方便地在类或结构中支持 foreach 迭代,而不必实现整个 IEnumerable 接口。
迭代器的返回类型必须为 IEnumerable、IEnumerator、IEnumerable<T> 或 IEnumerator<T>。当编译器检测到迭代器时,它将自动生成 IEnumerable 或 IEnumerable<T> 接口的 Current、MoveNext 和 Dispose 方法。
yield 关键字用于指定返回的值。到达 yield return 语句时,会保存当前位置。下次调用迭代器时将从此位置重新开始执行。而yield break则可以中止迭代,下面的代码有助于理解这点。
public class CityCollection : IEnumerable<string> { public IEnumerator<string> GetEnumerator() { yield return "New York"; yield return "Paris"; yield return "London"; } }
会依次打印出"New York", "Paris" "London". 有时候迭代器与迭代一起可以产生奇妙的效果,但也会耗费大量的内存。
IEnumerable<T> ScanInOrder(Node<T> root) { if(root.LeftNode != null) { foreach(T item in ScanInOrder(root.LeftNode)) { yield return item; } } yield return root.Item; if(root.RightNode != null) { foreach(T item in ScanInOrder(root.RightNode)) { yield return item; } } }
foreach语句会隐式地调用集合的无参的GetEnumerator方法來得到一個迭代器。一个集合类中只能定义一个这样的无参的GetEnumerator方法,不过我们也可以在类中实现多个迭代器,但每个迭代器都必须像任何类成员一样有唯一的名称。
using System.Collections.Generic; public class Stack<T>: IEnumerable<T> { T[] items; int count; public void Push(T data) {...} public T Pop() {...} public IEnumerator<T> GetEnumerator() { for (int i = count – 1; i >= 0; --i) { yield return items[i]; } } public IEnumerable<T> TopToBottom { get { return this; } } public IEnumerable<T> BottomToTop { get { for (int i = 0; i < count; i++) { yield return items[i]; } } } }
TopToBottom属性的get访问器只返回this,因为Stack本身就是一个可枚举类型。BottomToTop屬性使用C#迭代器返回了另一个可枚举接口。
实现IEnumerable接口的类看起来非常象一个枚举器工厂类,每次都产生一个独立的IEnumerator类。
using System; using System.Collections.Generic; class Test { static IEnumerable<int> FromTo(int from, int to) { while (from <= to) yield return from++; } static void Main() { IEnumerable<int> e = FromTo(1, 10); foreach (int x in e) { foreach (int y in e) { Console.Write("{0,3} ", x * y); } Console.WriteLine(); } } }
上面的代码打印了一个从1到10的乘法表。注意FromTo方法只被调用了一次用来产生实现了IEnumerable接口的变量e。而e.GetEnumerator()被调用了多次(通过foreach语句)來产生多个相同的迭代器。這些迭代器都封裝了FromTo声明中指定的代碼。注意,迭代其代码的时候改变了from参数。但是,迭代器是独立的,因此对于from参数和to参数,每個迭代器有它自己的一份拷贝。
评论
4 楼
ray_linn
2009-06-14
再给一段我实际工作中的例子,不借助yield return,代码就必须借助IList,其结果是无法干净优雅
public static IEnumerable<String> GetListOfMountPoints() { StringBuilder buffer = new StringBuilder((int)N, (int)N); IntPtr hVolumn = Volume.FindFirstVolume(buffer, N); do { String volumn = buffer.ToString(); IntPtr hMountPoint = Volume.FindFirstVolumeMountPoint(volumn, buffer, N); do { yield return buffer.ToString(); } while (Volume.FindNextVolumeMountPoint(hMountPoint, buffer, N)); Volume.FindVolumeMountPointClose(hMountPoint); } while (Volume.FindNextVolume(hVolumn, buffer, N)); Volume.FindVolumeClose(hVolumn); }
3 楼
kulinglei
2009-06-12
NightTree 写道
lz给深入讲讲委托吧。。。
java转c#的人,总感觉委托比其他东西难理解些。。。
java转c#的人,总感觉委托比其他东西难理解些。。。
期待中,我只知道他用的是函数指针 c转c#的人
2 楼
NightTree
2009-06-11
lz给深入讲讲委托吧。。。
java转c#的人,总感觉委托比其他东西难理解些。。。
java转c#的人,总感觉委托比其他东西难理解些。。。
1 楼
kulinglei
2009-06-10
积分又50了,该接je的老底了啊
发表评论
-
NET 4.0 多任务编程 之三 改进的线程池
2010-07-16 14:58 2228其实从.NET设计之初中就 ... -
NET 4.0 多任务编程 之四 Parallel初体验
2010-07-16 14:23 2166在.NET Framework 4.0中,在 ... -
.NET 4.0 多任务编程 之二 线程安全的集合
2010-07-14 13:54 3464随着多核计算机的普及 ... -
【C#】在C#中引用CygWin和MingW的Dll
2010-06-20 08:47 0在Windows上引入Unix或Linux的软件包,一般有以下 ... -
Java 7 闭包 -- 向C#学得更多
2010-06-08 10:55 210什么是闭包 简单来讲,闭包允许你将一些行为(包括语法和表达式 ... -
【Ray谈C#] MEF 扩展性管理框架
2010-05-28 16:58 3990原文发表于:blogs.ejb.cc M ... -
【Ray谈C#】乌龟爬之SynchronizationContexts
2010-05-19 15:09 2092为什么需要SynchronizationC ... -
用DLR创建自己的语言之一
2010-01-04 14:35 2536原文刊登于: http://www.bitwisemag.co ... -
C# 语法书 之可选参数
2009-12-22 14:40 2936适用C#版本:4.0以后 首 ... -
C# 语法书 <3> 静态类,别名等等
2009-06-30 11:32 1759最近比较忙,所以先跳 ... -
初窥Nemerle语言
2009-06-23 14:23 1742Nemerle是Microsoft的研究项目之一,由 Wroc ... -
C# 语法书 <2> 委托 delegate
2009-06-15 16:40 1883为什么要有委托? 先 ... -
What's New in C# 4.0 之一 语法
2009-06-08 14:54 24011. dynamic简介 在之前的文章有简单的谈到dynam ... -
What's New in .net 4.0 - 基础类库
2009-06-01 10:34 11491. System.Numerics.BigInteger ... -
一切为了并行:MS Axum语言教程 <四>
2009-05-14 15:12 1214数据流网编程 在程序中,代理之间通过发送和接受消息彼此沟通, ... -
一切为了并行: MS Axum语言教程 <三>
2009-05-13 14:35 1417域与状态共享 消息传递是种优秀的沟通机制,但它要消息中的数据 ... -
一切为了并行:MS Axum语言教程 <二>
2009-05-12 15:12 1019代理编程 上面的斐波那契数列的例子只是展示了一个微不足道的构 ... -
一切为了并行:MS Axum语言教程 <一>
2009-05-12 10:47 1454原文和更新参见: Ray Li ... -
C# 4.0中的契约式编程
2009-04-24 11:19 2884一切从质量谈起 许多 ... -
C# 利用范型与扩展方法重构代码
2008-04-03 14:58 2611在一些C#代码中常常可以看到 //An Simple Ex ...
相关推荐
C# 2.0版本引入了许多重要的新特性,其中最值得关注的是**泛型**、**匿名方法**、**迭代器**等。 ##### 1. 泛型 泛型是C# 2.0中最重要的新特性之一,它允许开发者编写类型安全的代码,这些代码可以针对任何数据...
例如,IAsyncEnumerable<T>接口提供了异步迭代器,使得异步流式处理成为可能。 九、C#的新特性 随着版本的更新,C#不断引入新的特性和改进。例如,C# 6引入了null条件运算符?.和null合并运算符??;C# 7.0引入了模式...
9. **类型安全的集合初始化器**:这使得我们可以使用简洁的语法来初始化集合,如`new List<int> { 1, 2, 3 }`。 10. **可空引用类型**:C# 2.0引入了可空引用类型,允许引用类型的值为`null`,增强了代码的健壮性。...
编译器在将C#代码转化为MSIL(Microsoft Intermediate Language)时,会识别并转换LINQ查询表达式,将它们转化为标准的迭代器模式或者其他合适的代码结构。这样,原本在SQL中才有的`select`、`from`、`where`、`...
书中前面讲了1.1的语法后面是2.0的泛型,迭代器,匿名方法。没有设计高级知识。
迭代器块是C# 2005中的另一个新增特性,它简化了编写迭代器的代码。以前,创建一个枚举器需要实现`IEnumerator`接口,现在只需定义一个返回`IEnumerable<T>`的函数,并使用`yield return`关键字来提供序列中的每个...
4. **泛型**:泛型是C# 2.0的一大亮点,它提供了类型安全的容器,如List<T>和Dictionary<TKey,TValue>。泛型使得代码更加通用,提高了效率并减少了类型转换的需要。 压缩包内的源文件01-05,很可能是对这些特性的...
7. **迭代器**:迭代器使开发者能够自定义迭代过程,如在`yield return`语句中实现。它们常用于实现`IEnumerable<T>`接口,使自定义类型能像数组和列表一样被遍历。 8. **泛型约束**:C# 3.0增强了泛型约束,如`...
此外,C# 2005引入了泛型,这是一种强大的工具,可以创建类型安全且可重用的数据结构,如List<T>和Dictionary<TKey, TValue>。书中的例子可能会展示如何使用泛型来提高代码的灵活性和效率。 在文件名称列表中,我们...
5. **数组与集合**:书中会介绍一维和多维数组,以及.NET框架提供的ArrayList和Generic Collections,如List<T>。 6. **泛型**:C# 2.0引入了泛型,允许创建类型参数化的类、接口和方法,以提高代码的复用性和效率...
- 在C#中,可以通过在类型声明(如类、接口或方法)中使用尖括号`<>`来定义一个泛型类型。例如: ```csharp public class GenericClass<T> { // 成员 } ``` 使用泛型类型时,需要提供具体的类型参数,称为...
1. **C# 2005基础语法**:C# 2005是.NET Framework 2.0的一部分,引入了许多新的特性和改进,如匿名方法、迭代器、Partial类、Lambda表达式等。G子文件可能包含这些语法的应用实例,帮助读者理解它们的用法和优点。 ...
书中涵盖了C# 3.0版本的所有关键知识点,包括 LINQ、匿名方法、Lambda表达式、泛型、迭代器以及面向服务的编程等。 1. **C#基础**:书中首先介绍了C#的基础语法,如变量、数据类型、控制流语句(如if、for、while)...
11. 集合与泛型集合:C#提供了丰富的集合类,如List<T>、Dictionary<TKey, TValue>等,这些类都实现了通用接口如IEnumerable<T>,便于进行迭代和操作。 12. 错误处理:C#通过try-catch-finally语句块来处理异常,...
13. **类型安全的ArrayList和Hashtable**:C# 2.0提供了List<T>和Dictionary<TKey, TValue>等类型安全的集合,避免了类型转换的麻烦。 通过学习《C#2.0完全自学手册》,你不仅能掌握C# 2.0的基本语法和特性,还能...
11. **集合与泛型集合**:C#提供了多种内置的集合类,如List<T>、Dictionary<TKey,TValue>等,它们实现了泛型,提供了强类型的安全性和性能优化。 12. **并发和并行编程**:C#支持多线程和任务并行库(TPL),以及...
6. 进阶特性:包括匿名方法、迭代器、匿名类型等较高级的概念。 7. C#在.NET平台的应用:例如使用.NET框架提供的各种命名空间和类库。 8. 与COM技术的互操作性:如何在C#中使用COM组件以及如何将C#组件暴露给COM环境...
1. **C#基础**:C# 2005是.NET Framework 2.0版本的一部分,引入了诸如匿名方法、迭代器和部分类型等新特性。这个系统利用了C#的基础语法,如类、对象、属性、方法等,展示了面向对象编程的基本理念。 2. **Windows...
1. **语法基础**:C#的语法与C++和Java有诸多相似之处,但也有其独特之处。包括基本数据类型(如int、double、bool等)、变量声明、常量、运算符、控制流语句(如if-else、switch-case、for、while等)以及函数的...