C# List 接口 源码分析

   最近有兴趣看看微软开放的.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();(重置)

其他的

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值