对于 飞林沙的<把Array说透>的扩展


    今天看到 飞林沙同学的两个帖子
     把Array说透 把Array说透序一 这两个帖子都是从很底层的原理以及来说Array数组,看了让人很受启发,所以我想写一篇从FCL的角度来阐述数组的文章,权当抛砖引玉,高手请飘走....
    
     System.Array
         地球人都知道,所有的数组都是隐式的派生于这个基类。在MSDN里可以发现System.Array的原型是:
        
1  [SerializableAttribute]
2  [ComVisibleAttribute( true )]
3  public   abstract   class  Array : ICloneable, 
4      IList, ICollection, IEnumerable
5 

      而几乎所有Array所具备的功能都是实现这几个接口.下面说说这几个接口之间的关系。
    
    IEnumerable
          这个接口就是传说中的祖宗,是IList和ICollection接口的父接口.这个接口只有一个方法.GetEnumerator(),这也是.net FCL对实现迭代器模式的接口。在.net中,所有实现了IEnumerable接口的类才能用foreach关键字进行遍历.
            IEnumberator
            实现
IEnumberator接口的类是IEnumerable接口GetEnumerator()方法返回的类型,表示是集合中当前的元素,实现IEnumberator接口需要实现两个方法和一个属性
           IEnumberator内部有MoveNext()方法和Reset()方法,从名字不难看出,前者的用处是返回集合中下一个需要被遍历的元素,而Reset()方法让当前的Enumberator回到集合中的第一个元素.
           IEnumberator还有Current属性,返回集合中Enumberator中当前的元素.
           下面通过MSDN中的代码来对这两个接口进行说明:
           
ContractedBlock.gif ExpandedBlockStart.gif Msdn中对IEunmerable接口的代码演示
  1using System;
  2using System.Collections;
  3
  4public class Person
  5ExpandedBlockStart.gifContractedBlock.gif{
  6    public Person(string fName, string lName)
  7ExpandedSubBlockStart.gifContractedSubBlock.gif    {
  8        this.firstName = fName;
  9        this.lastName = lName;
 10    }

 11
 12    public string firstName;
 13    public string lastName;
 14}

 15
 16public class People : IEnumerable
 17ExpandedBlockStart.gifContractedBlock.gif{
 18    private Person[] _people;
 19    public People(Person[] pArray)
 20ExpandedSubBlockStart.gifContractedSubBlock.gif    {
 21        _people = new Person[pArray.Length];
 22
 23        for (int i = 0; i < pArray.Length; i++)
 24ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 25            _people[i] = pArray[i];
 26        }

 27    }

 28
 29    public IEnumerator GetEnumerator()
 30ExpandedSubBlockStart.gifContractedSubBlock.gif    {
 31        return new PeopleEnum(_people);
 32    }

 33}

 34
 35public class PeopleEnum : IEnumerator
 36ExpandedBlockStart.gifContractedBlock.gif{
 37    public Person[] _people;
 38
 39    // Enumerators are positioned before the first element
 40    // until the first MoveNext() call.
 41    int position = -1;
 42
 43    public PeopleEnum(Person[] list)
 44ExpandedSubBlockStart.gifContractedSubBlock.gif    {
 45        _people = list;
 46    }

 47
 48    public bool MoveNext()
 49ExpandedSubBlockStart.gifContractedSubBlock.gif    {
 50        position++;
 51        return (position < _people.Length);
 52    }

 53
 54    public void Reset()
 55ExpandedSubBlockStart.gifContractedSubBlock.gif    {
 56        position = -1;
 57    }

 58
 59    public object Current
 60ExpandedSubBlockStart.gifContractedSubBlock.gif    {
 61        get
 62ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 63            try
 64ExpandedSubBlockStart.gifContractedSubBlock.gif            {
 65                return _people[position];
 66            }

 67            catch (IndexOutOfRangeException)
 68ExpandedSubBlockStart.gifContractedSubBlock.gif            {
 69                throw new InvalidOperationException();
 70            }

 71        }

 72    }

 73}

 74
 75class App
 76ExpandedBlockStart.gifContractedBlock.gif{
 77    static void Main()
 78ExpandedSubBlockStart.gifContractedSubBlock.gif    {
 79        Person[] peopleArray = new Person[3]
 80ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 81            new Person("John""Smith"),
 82            new Person("Jim""Johnson"),
 83            new Person("Sue""Rabon"),
 84        }
;
 85
 86        People peopleList = new People(peopleArray);
 87        foreach (Person p in peopleList)
 88            Console.WriteLine(p.firstName + " " + p.lastName);
 89
 90    }

 91}

 92
 93ExpandedBlockStart.gifContractedBlock.gif/**//* This code produces output similar to the following:
 94 * 
 95 * John Smith
 96 * Jim Johnson
 97 * Sue Rabon
 98 * 
 99 */

100
101
102

      ICollection
         
这个接口直接继承自IEnumerable接口,这个接口是System.Collections命名空间的基本接口,从这个接口开始就有一些数组特性了. 实现ICollection接口需要实现4个方法(包括从IEnumerable继承来的一个方法),和一个属性
          ICollection所具有的3个方法是AddAt,AddItem,Item这三个方法,AddAt和AddItem方法均是添加一个元素到集合,AddAt可以选择集合中 的任何位置进行插入,而AddItem方法默认将元素插入队尾。
          ICollection的属性是表示当前集合大小的Count属性.
      IList
          IList又直接继承与ICollection接口和IEnumerable接口,从IList开始,集合开始拥有更强大的功能,可以简单理解为IList主要针对动态集合,而ICollection主要针对静态集合.IList里包含了操作集合比较完整的方法 ,比如添 加元素的Add方法,插入到指定元素的Insert方法,清楚所有元素的Clear方法,以及是否存在元素的Contains方法.

      Array与IList
          虽然Array实现了IList接口,但Array中并不支持IList中的某些方法。比如Contains这样的方法。有人会好奇为什么Array实现了IList接口还不能使用里面的方法呢?因为C#中数组是定长的,而IList是动态的,所以FCL中通过 显式实现 IList中的某些方法是Array不具有IList中的某些方法。如果想在Array中使用IList的方法,那首先要将Array转换为IList
   
     IList实现了ICollection,而ICollection实现了IEnumerable,为什么数组还要实现上面3个接口呢,实现IList不就好吗
          这个问题我在网上查的资料有两点
          1.提高代码可读性(这个我想是最重要一条)
          2.方便类型转换(其实这个也是提高代码可读性的一部分)

      ICloneable
           这个接口自成一家,和其他Array实现的接口毫不相干,这个接口是FCL实现设计模式中的原型模式(prototype),在这里其实就是浅复制(shallow copy)功能.

      IList<T>,IEnumerable<T>,IEnumerat or<T>
            这几个接口都是.net 2.0引入的泛型接口,上面所说的接口中除了ICloneable的其他接口都存在于System.Collections命名空间中,而泛型接口存在于System.Collections.Generics命名空间中。泛型我想大家都不陌生了,这里就不讨论了,在这里只想说有了泛型后,前面的接口可以基本不用了:-)
   
      
     高手请拍砖................
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值