最近有兴趣看看微软开放的.net "源码" ,主要对几个类进行讨论 集合类,线程,界面类等,首先集合类我以List 类主要讨论三个问题
1.遍历问题 IEnumerable
2.添加删除(查询)IList
3.线程安全 ICollection
从三个问题进行分析List中怎么实现,主要目的去思考怎么才能向.net一样去解决复杂的问题,
1.List 集合类
List 继承 几个重要的接口 :IList<T>, ICollection<T>, IEnumerable<T>
1.IEumerable的作用: 支持非泛型的枚举器
public interface IEnumerable
{
// Token: 0x06003785 RID: 14213
[DispId(-4)]
[__DynamicallyInvokable]
IEnumerator GetEnumerator();
}
IEumerable<T>支持泛型类型的枚举器
using System;
using System.Runtime.CompilerServices;
namespace System.Collections.Generic
{
// Token: 0x020004A6 RID: 1190
[TypeDependency("System.SZArrayHelper")]
[__DynamicallyInvokable]
public interface IEnumerable<out T> : IEnumerable
{
// Token: 0x0600399E RID: 14750
[__DynamicallyInvokable]
IEnumerator<T> GetEnumerator();
}
}
List 只继承了 IEumerable<T>、 IEumerable接口,但是还有 继承IEumerator的类
public List<T>.Enumerator GetEnumerator()
{
return new List<T>.Enumerator(this);
}
// Token: 0x060039E2 RID: 14818 RVA: 0x000DB68B File Offset: 0x000D988B
[__DynamicallyInvokable]
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return new List<T>.Enumerator(this);
}
// Token: 0x060039E3 RID: 14819 RVA: 0x000DB698 File Offset: 0x000D9898
[__DynamicallyInvokable]
IEnumerator IEnumerable.GetEnumerator()
{
return new List<T>.Enumerator(this);
}
Enumerator是List中一个结构体
using System;
using System.Collections;
using System.Collections.Generic;
// Token: 0x02000BAB RID: 2987
[__DynamicallyInvokable]
[Serializable]
public struct Enumerator : IEnumerator<T>, IDisposable, IEnumerator
{
// Token: 0x06006DEA RID: 28138 RVA: 0x0017AA08 File Offset: 0x00178C08
internal Enumerator(List<T> list)
{
this.list = list;
this.index = 0;
this.version = list._version;
this.current = default(T);
}
// Token: 0x06006DEB RID: 28139 RVA: 0x0017AA30 File Offset: 0x00178C30
[__DynamicallyInvokable]
public void Dispose()
{
}
// Token: 0x06006DEC RID: 28140 RVA: 0x0017AA34 File Offset: 0x00178C34
[__DynamicallyInvokable]
public bool MoveNext()
{
List<T> list = this.list;
if (this.version == list._version && this.index < list._size)
{
this.current = list._items[this.index];
this.index++;
return true;
}
return this.MoveNextRare();
}
// Token: 0x06006DED RID: 28141 RVA: 0x0017AA91 File Offset: 0x00178C91
private bool MoveNextRare()
{
if (this.version != this.list._version)
{
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
}
this.index = this.list._size + 1;
this.current = default(T);
return false;
}
// Token: 0x170012F8 RID: 4856
// (get) Token: 0x06006DEE RID: 28142 RVA: 0x0017AACD File Offset: 0x00178CCD
[__DynamicallyInvokable]
public T Current
{
[__DynamicallyInvokable]
get
{
return this.current;
}
}
// Token: 0x170012F9 RID: 4857
// (get) Token: 0x06006DEF RID: 28143 RVA: 0x0017AAD5 File Offset: 0x00178CD5
[__DynamicallyInvokable]
object IEnumerator.Current
{
[__DynamicallyInvokable]
get
{
if (this.index == 0 || this.index == this.list._size + 1)
{
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);
}
return this.Current;
}
}
// Token: 0x06006DF0 RID: 28144 RVA: 0x0017AB06 File Offset: 0x00178D06
[__DynamicallyInvokable]
void IEnumerator.Reset()
{
if (this.version != this.list._version)
{
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
}
this.index = 0;
this.current = default(T);
}
// Token: 0x040034FB RID: 13563
private List<T> list;
// Token: 0x040034FC RID: 13564
private int index;
// Token: 0x040034FD RID: 13565
private int version;
// Token: 0x040034FE RID: 13566
private T current;
}
已经很明显了,Enumerator 帮助 List类实现IEnumerator<T>, IDisposable, IEnumerator,在其中写法有一些有意思的东西。Enumerator是结构体,了解一下Struct
可以看出工具类或者辅助类,.net 一般用static、struct,注意这方面很必要,工具类不要实例化,比如主要操作数据类Array是静态类,
这里来思考一下,.net 如何解决问题集合类遍历的问题
1.List为什么用struct来实现接口函数
2.为什么要3个接口,IEumerable,IEumerable<T>,IEumerator这三个接口,带着问题看下面的例子
using System;
using System.Collections;
namespace ConsoleApplication1
{
class Shape : IEnumerator
{
string[] _Shapes;
int _Position = -1;
public Shape(string[] _theShapes)
{
_Shapes = new string[_theShapes.Length];
for( int i = 0; i < _theShapes.Length; i++ )
{
_Shapes[i] = _theShapes[i];
}
}
public Object Current
{
get
{
if ( _Position == -1 )
throw new InvalidOperationException();
if (_Position >= _Shapes.Length)
throw new InvalidOperationException();
return _Shapes[_Position];
}
}
public bool MoveNext()
{
if (_Position < _Shapes.Length - 1)
{
_Position++;
return true;
}
else
return false;
}
public void Reset()
{
_Position = -1;
}
}
class Component : IEnumerable
{
string[] shapes = { "Circular", "spherical", "Quadrilateral", "Label" };
public IEnumerator GetEnumerator()
{
return new Shape( shapes );
}
}
class Program
{
static void Main(string[] args)
{
Component comp = new Component();
foreach ( string oshape in comp )
Console.WriteLine(oshape);
}
}
}
看得出来,要完成遍历至少需要两个接口,IEumerator是真正对集合简单迭代,要完成遍历功能设计几个成员
bool MoveNext();(下一个)
object Current { [__DynamicallyInvokable] get; (当前对象)
void Reset();(重置)
其他的