zoukankan      html  css  js  c++  java
  • C#高级编程笔记 Day 5, 2016年9月 13日 (泛型)

    【重点】泛型:有了泛型,就可以创建独立于被包含类型的类和方法了。我们不必给不同的类型编写功能相同的许多方法和类,只创建一个方法或类即可,以下是泛型的特点:性能、类型安全性、二进制代码重用、代码的扩展、命名约定

      1、性能:空间的泛型和非泛型集合类 System.Collections 和 System.Collections.Generic

        值类型存储在栈上,引用类型存储在堆上。 C# 类 是引用类型,结构是值类型。 .NET很容易把值类型转换为引用类型,所以可以在需要对象(对象是引用类型)的任何地方使用值类型。例如,int 可以赋予一个对象。从值类型转换为引用类型成为装箱。如果方法需要把一个对象作为参数,同时传递一个值类型,装箱操作就会自动进行。另一方面,装箱的值类型可以使用拆箱操作转换为值类型。在拆箱时,需要使用类型强制转换运算符。

      [延伸]装箱和拆箱

    【装箱和拆箱】
    下面可以像处理对象那样处理字面值:
        string s=10.ToString();//隐式转换
    
    C#通过拆箱(unboxing)和装箱(boxing)可以把值类型转换为引用类型,并把引用类型转换回值类型。
        【装箱】:用于描述把一个值类型转换为引用类型。运行库会为堆上的对象创建一个临时的引用类型“箱子”。
        int myIntNumber=20;
        object myObject=myIntNumber; //显示转换
        
        【拆箱】用于描述相反的过程,其中以前 装箱的值类型 强制转换回 值类型。这里使用术语 “强制转换”,是因为这种转换时显示进行的。
        int myIntNumber=20;
        object myObjet=myIntNumber;//把 myIntNumber 进行装箱
        int mySecondNumber=(int)myObject;//拆箱 强制转换
        
        ★只能对以前装箱的变量进行拆箱,当myObject 不是装箱后的int 型时,如果执行最后一行就会抛出异常。
    
        !!这里有一个警告,在拆箱时,必须非常小心,确保得到的值变量有足够的空间存储拆箱的值中的左右字节。例如 C# 的int 有 32位 ,所以把 long 值(64位) 拆箱为 int 时,会导致一个 InvalidCastException 异常。
        long myLongNumber=32323131;
        object myObject=myLongNumber;
        int myIntNumber=(int)myObject;

      例 System.Collection 中的 ArrayList类中进行的拆箱装箱操作 ArrayList存储对象,Add()方法定义为需要把一个对象作为参数。

    1 var list=new ArrayList();
    2 list.add(44);//进行装箱,把值类型转换为引用类型
    3 int i1=(int)list[0];//拆箱
    4 
    5 foreach(int i2 in list)
    6 {
    7     Console.WriteLine(i2);//进行拆箱
    8 }

      >>装箱和拆箱很容易使用,但性能损失比较大,遍历许多项时尤其如此。

      

      System.Collections.Generic 中的 List<T> 类不使用对象,而是在使用时定义类型。在下面的例子中,List<T> 类的泛型定义为 int ,所以int 类型在JIT 编译器动态生成的类中是 int,不再进行拆箱装箱

    1 var list=new ArrayList<int>();
    2 list.Add(22);//不在进行装箱
    3 int i1=list[0]; //不再进行拆箱 转换
    4 foreach(int i2 in list)
    5 {
    6     Console.WriteLine(i2);
    7 }

      2、类型安全

       与ArrayList 类一样,如果使用对象,就可以在这个集合中添加任意类型。下面的例子在ArrayList类型的集合中添加一个整数、一个字符串和一个MyClass 类型的对象;

        

     1 var list=new ArrayList();
     2 
     3 list.Add(22);
     4 list.Add("GellW");
     5 list.Add(new MyClass());
     6 
     7 //当使用下面的foreach 来迭代时,并不是所有元素都可以强制转换为 int 就会抛出一个运行异常
     8 foreach(int i2 in list)
     9 {
    10     Console.WriteLine(i2);
    11 }

      若在泛型类 List<T> 中泛型类型 T 定义了允许使用的类型。有了 比如 List<int> 的定义,就只能把整数类型添加到集合中。编译器就不会编译这段代码,因为 Add 的参数无效

      

    1 var list=new ArrayList<int>();
    2 list.Add(44);
    3 list.Add("Geell");//编译时错误
    4 list.Add(new MyClass());//编译时错误。

      【扩展】

      

    var : 该变量需要根据初始化表达式来推断变量的类型,而且只能是局部变量。在声明时必须同时赋值。

      3、二进制代码的重用

    1 var list1=new List<int>();
    2 list1.Add(44);
    3 
    4 var list2=new List<stirng>();
    5 list2.Add("Stringhisdm");
    6 
    7 var list3=new List<MyClass>();
    8 list3.Add(new MyClass());

      4、命名约定

      • 泛型类型的名称用字母T 作为前缀。
      • 如果没有特殊要求,泛型类型允许使用任意类替代,且只是用了一个泛型类型,就可以用字符T作为泛型类型的名称。    
      • 1 public class List<T>{}
        2 
        3 public class LinkedList<T>{}
      • 如果泛型类型有特定的要求(例如,它必须实现一个接口或派生自基类),或者使用了两个或多个泛型类型,就应给泛型类型使用描述性的名称: 
      • 1 public delegate void EventHandle<TEventArgs>(object sender,TEventArgs e);
        2 
        3 public delegate TOutput Converter<TInput,TOutput>(TInput from);
        4 
        5 public class SortedList<TKey,TValue>{}
  • 相关阅读:
    Python基础:Python函数、文件操作、递归
    Python面向对象高级编程:__slot__(给实例添加方法、属性)
    Python fullstack系列【1】:初识Python
    Python fullstack系列【2】Python数据类型
    liunux联网方式配置
    使用 SercureSRT连接linux虚拟机
    高质量代码css部分笔记,未实验
    一段代码
    让图片算好高宽再显示
    你正在成长为一名优秀的程序员吗?
  • 原文地址:https://www.cnblogs.com/xiyin/p/5868958.html
Copyright © 2011-2022 走看看