zoukankan      html  css  js  c++  java
  • 集合与泛型

    hi,you guys。

    今天我们继续学习<叩响c#之门>,今天我们学习的内容是集合与泛型。集合、泛型是我们项目开发中经常会用的知识。学好泛型、集合,对我们开发工作有很大的帮助。

    集合

    物以类聚,相同的东西需要归于一类。我们常常将相互关联的对象组成集合,自然数组成自然数集。同班同学组成班级,诗人做的诗篇,组成诗集。集合中的对象,称为元素(Element)。C#为我们提供一组功能强大的集合类,实现了多种不同类型的集合,我们可以根据实际用途选择恰当的集合类型。下表,是FCL(Framework Common Library)类库为我们提供的部分集合类。

    QQ Photo20140823155454

    除了Array在System命名空间下,其余的类都位于System.Collections命名空间下。这些类通过直接或间接的继承一些接口,来实现其自身强大的功能。我们之前在项目中用过foreach循环语句,遍历一个集合或数据集。那么是如何foreach是如何实现对集合或数据集的遍历的呢?(与其说是遍历,不如说是迭代。关于迭代概念,大家可以参考一些数据结构书籍的递归算法)。原来FCL提供的集合类,都直接或间接的实现了IEnumerable接口,这个接口声明了一个名为GetIEnumerator()方法。这个方法返回一个继承了IEnumerator接口的类,我们通常将这个类称为迭代器。

    //IEnumerable接口
    public interface IEnumerable
    {
         IEnumerator GetIEnumerator();
    }

    IEnumerable接口类

    //IEnumerator接口
    public interface IEnumerator
    {
         bool MoveNext();      //获取下一个元素
         object Current{get;}  //获取当前元素
          void Reset();        //将枚举数设置为其初始位置
    }

    IEnumerator接口类

    foreach语句就是通过访问迭代器来获取集合中的元素。ICollection接口也是一个很基础的接口,它继承了IEnumerable接口,并且添加了一个Copy()方法,和一个Count属性以及两个用于同步的属性。

    //ICollection接口
    public interface ICollection:IEnumerable
    {
         void Copy(System.Array array,int index);  //复制到数组
          int Count{get;}                           //元素个数
         bool IsSynchronized;                      //是否同步
        object SyncRoot{get;}                     //用于同步的对象   
    }

    IList接口、IDictionary接口都继承于ICollection接口。

    关于各个集合类的一些方法,大家可以下去自己练习一下。因为,本章主要讲解的是泛型类。其实,在项目中大家更多的会去使用泛型,因为集合存在一个弊端。

    集合类的弊端

    大家看看下面的代码:

     ArrayList list=new ArrayList();
     lsit.Add(10);         //添加元素
     int n=(int)lsit[0];   //取出元素

    因为所有类型都继承于object的类型,所以当我们调用.Add()方法,向集合中添加元素时,系统会默认为object类型。此时,如果添加的元素不是引用类型而是值类型,那么在向集合添加元素时,就会进行装箱操作,将值类型转换为引用类型。同样,在我们读取元素时,需要拆箱操作,将object的类型转换为值类型。这样做,会有三个缺点:

    第一、在装箱、拆箱的过程中,可能会造成一定的性能损失。

    第二、什么类型的数据都往集合中放,不利于编译器进行严格的类型安全检查。

    第三、显示转换类型,降低了程序的可读性。Note(现在计算机越来越快,性能也不是唯一目标了。软件开发成本在于软件维护与升级。所以,提高代码可读性可以降低软件开发成本呢。)

    ArrayList   list=new ArrayList();
    list.Add(10);
    list.Add("hello");
    foreach(int element in list)
    {
       int n=(int)element;
    }

    上面这段代码,编译不会出错。运行会出现,因为”hello”不能转换为int类型。现在大家看出集合类的弊端了吧,那么泛型类又有什么地方强于集合呢?其实不难想象,泛型强于集合的地方,一定是集合比较薄弱的地方。集合薄弱的地方就在,集合类的元素类型没有限制。

    泛型

    泛型与集合的功能基本一致,唯一的不同点在于,泛型类的元素类型受我们控制,是我们指定的类型,而不是万物之祖的object类型。泛型具有一个参数列表<T>,在整个类里用T代表元素类型,T的类型是不确定的,是抽象类型。在我们实例化类时,将抽象类型的元素具体化,具体类型的参数将代替T。看程序:

    // 泛型类
     public class  Generic<T>
    {
           public void Check()
            {
               Console.WriteLine(this.GetType()); //输出T的类型         
            }     
    }
    
    
    //实例化泛型类
    Generic<int>  instanceInt=new Generic<int>();
     instanceInt.Check(); //输出的类型为System.Int32
    
    Generic<String>  instanceString=new Generic<String>();
    instanceString.Check();  //输出的类型为System.String;

      泛型类中的T,是抽象类型。实例化时,才会将其具体化。例如上面的instanceInt,就是将泛型类中的T,具体化为Int类型。instanceString,就泛型类的T具体化为String类型.我们可以定义泛型类,同意也可定义泛型方法,泛型接口等。看下面的代码:

    //泛型类
    public static void Swap<T>(ref T a,ref T b)
    {
            T t=a;
             a=b;
             b=t;
    }

    此时的a,b都是抽象的,都是未知的类型。

    Static void Main(string[] args)
    {
       int x=100;
       int y=200;
      Swap<int> (ref x,ref y);
    Console.WriteLine("x={0},y={1}",x,y);
    }

    我们在调用泛型方法时,将参数具体化了。

    C#为我们提供了一些泛型类:

    List<T>
    Stack<T>
    Queue<T>
    SortedList<TKey,TValue>
    Dictionary<TKey,TValue>

    关于他们的一些方法,大家可以查看相关手册。学会通过查看手册来学习编程,是很重的。好了今天的泛型、集合就到这里了。最后,我把作者讲的一句话,给大家分享一下。“实践中磨练编程技能,思考中感悟编程本质”。

  • 相关阅读:
    对于进程的理解
    反汇编引擎实现——流程分析
    window异常处理——except_handler4以及栈展开分析
    对于硬盘驱动的理解
    对文件系统的理解
    移动端适配flexible.js
    vue学习(5)-评论功能(利用父组件的方法)
    vue学习(4)-组件的创建,父子组件传值,$refs
    vue学习(3)-增删改查
    vue学习(2)-过滤器
  • 原文地址:https://www.cnblogs.com/VitoCorleone/p/3931513.html
Copyright © 2011-2022 走看看