序
学生时期,有过小组作业,当时分工一人做那么两三个页面,然而在前端差不多的时候,我和另一个同学发生了争执。当时用的是简单的三层架构(DLL、BLL、UI),我个人觉得各写各的吧,到时候合并,而他觉得应该把底层先写好,他好直接调用中间层的方法。
到出来工作之后,接触接口,想整理一下这个:接口到底是个什么概念呢?
需要说明一点的是,我这里说的接口,不是API那个接口,而是“暂时没实现”那个接口。
刚接触接口类型的时候,还不太熟练,看到返回接口类型的方法,总在奇怪,这个返回的对象怎么知道它取哪个实现?可以看一个简单的例子:
报错 (无法创建抽象类或接口的实例) |
var test = new ITestInterface(); |
正确 |
ITestInterface infa = new TestInterface(); infa.Func1(); |
也即,返回的类型总是具类,是确定的,方法已经实现的。
ITestInterface infa = new TestInterface();
其中的 ITestInterface 更像一个模具,对应这个模具造型的内容,由TestInerface提供。
那么,接口到底如何使用?
接口的使用,要这样看:“具备某种特征(功能)”。
例如看 ITestInterface infa = new TestInterface(); 其中,TestInterface具备有ITestInterface的特征,而ITestInterface作为有某种特征(功能)的标记,它对具体如何达到这种特征(功能)是不感兴趣的,有标记就有特征。这种标记的体现,在C#里面就是继承。
说到这里,老朋友IEnumerable是一定要介绍的。
一、迭代器 IEnumerable
集合这种数据结构是很常见的,通常的操作是对集合的内容做筛选,或排序。IEnumerable接口描述的是返回可循环访问集合的枚举数,继承这个接口,需要实现 public IEnumerator GetEnumerator() {} 方法。
那么,IEnumerator是个什么er?继承这个接口之后,IDE提示需要实现的方法——
public class Iterator : IEnumerator { public object Current => throw new NotImplementedException(); public bool MoveNext() { … } public void Reset() { … } }
有一个当前对象,一个是否能指向下一个的判断,还有一个重置。那么,可以想象迭代器应该是这样用的:
Iterator iterator = new Iterator(); while (iterator.MoveNext()) { // Get iterator.Current to do something.. Console.WriteLine(iterator.Current.ToString()); }
但这看起来,并不太聪明,或者这样使用比较“合理”:
是不是get到了某种真相?foreach里面接受的是IEnumerable对象,并且会在此处调用到GetEnumerator去得到Enumerator。那么到底public IEnumerator GetEnumerator(){}要怎么实现呢,C# 2已经提供了yield语句简化迭代器。
public class IterationSample : IEnumerable { public IEnumerator GetEnumerator() { for (int index = 0; index < values.Length; index++) { yield return values[(index + startingPoint) % values.Length]; } } public object[] values; public int startingPoint; public IterationSample(object[] values, int startingPoint) { this.values = values; this.startingPoint = startingPoint; } }
再来使用Enumerator:
object[] objs = new object[]{"a", "b", "c", "d"}; IterationSample sam = new IterationSample(objs, 0); foreach (var str in sam) { // do something.. }
可以想象,yield是个怎么样的存在,“一次一次返回”这是我对yield的第一印象描述。但总觉得还是有些说不清楚,这种时候还是得看看书:
“yield return 语句指表示 ’暂时地’ 退出方法——事实上,可以把它当做暂停”,
既然有这种说法,那还得给出个demo[1],关于怎么个“暂停”。
(这里悄咪咪用C# 6的新语法using static System.Console; 实在懒得打 Console.WriteLine();)
class Program { static void Main(string[] args) { IEnumerable<int> iterable = CreateEnumerable(); IEnumerator<int> iterator = iterable.GetEnumerator(); WriteLine("Starting to iterate"); while (true) { WriteLine("Calling MoveNext().."); bool result = iterator.MoveNext(); WriteLine($"MoveNext result = {result}"); if (!result) break; WriteLine("Fetching Current.."); WriteLine($"..Current result = {iterator.Current.ToString()}"); } ReadLine(); } static readonly string Padding = new string(' ', 30); static IEnumerable<int> CreateEnumerable() { WriteLine("Start of CreateEnumerable()"); for (int i = 0; i < 2; i++) { Wri