2014-07-29 19:04:01|?次阅读|上传:wustguangh【已有?条评论】发表评论
(1)源起
如果想给一个类型增加行为,一定要通过继承的方式实现吗?
不一定的!
(2)使用
来看看这段代码:
public static void PrintString(this String val) { Console.WriteLine(val); }
消费这段代码的代码如下:
var a = "aaa"; a.PrintString(); Console.ReadKey();
我想你看到扩展方法的威力了。
本来string类型没有PrintString方法
但通过我们上面的代码,就给string类型"扩展"了一个PrintString方法
(1)先决条件
<1>扩展方法必须在一个非嵌套、非泛型的静态类中定义
<2>扩展方法必须是一个静态方法
<3>扩展方法至少要有一个参数
<4>第一个参数必须附加this关键字作为前缀
<5>第一个参数不能有其他修饰符(比如ref或者out)
<6>第一个参数不能是指针类型
(2)注意事项
<1>跟前面提到的几个特性一样,扩展方法只会增加编译器的工作,不会影响性能(用继承的方式为一个类型增加特性反而会影响性能)
<2>如果原来的类中有一个方法,跟你的扩展方法一样(至少用起来是一样),那么你的扩展方法奖不会被调用,编译器也不会提示你
<3>扩展方法太强大了,会影响架构、模式、可读性等等等等....
· (1)使用
我们每次针对集合类型编写foreach代码块,都是在使用迭代器
这些集合类型都实现了IEnumerable接口
都有一个GetEnumerator方法
但对于数组类型就不是这样
编译器把针对数组类型的foreach代码块
替换成了for代码块。
来看看List的类型签名:
public class List<T> : IList<T>, ICollection<T>, IEnumerable<T>, IList, ICollection, IEnumerable
IEnumerable接口,只定义了一个方法就是:
IEnumerator<T> GetEnumerator();
(2)迭代器的优点:
假设我们需要遍历一个庞大的集合
只要集合中的某一个元素满足条件
就完成了任务
你认为需要把这个庞大的集合全部加载到内存中来吗?
当然不用(C#3.0之后就不用了)!
来看看这段代码:
static IEnumerable<int> GetIterator() { Console.WriteLine("迭代器返回了1"); yield return 1; Console.WriteLine("迭代器返回了2"); yield return 2; Console.WriteLine("迭代器返回了3"); yield return 3; }
消费这个函数的代码如下:
foreach (var i in GetIterator()) { if (i == 2) { break; } Console.WriteLine(i); } Console.ReadKey();
输出结果为:
迭代器返回了1
1
迭代器返回了2
大家可以看到:
当迭代器返回2之后,foreach就退出了
并没有输出“迭代器返回了3”
也就是说下面的工作没有做。
(3)yield 关键字
MSDN中的解释如下:
在迭代器块中用于向枚举数对象提供值或发出迭代结束信号。
也就是说,我们可以在生成迭代器的时候,来确定什么时候终结迭代逻辑
上面的代码可以改成如下形式:
static IEnumerable<int> GetIterator() { Console.WriteLine("迭代器返回了1"); yield return 1; Console.WriteLine("迭代器返回了2"); yield break; Console.WriteLine("迭代器返回了3"); yield return 3; }