C#高级编制程序笔记 Day 5, 2015年十一月 1七日 (泛型)

【重点】**泛型:有了泛型,就足以创立独立于被含有类型的类和章程了。大家不用给差异的品种编写作用雷同的大队人马艺术和类,只开创一个艺术或类即可,以下是泛型的本性:品质、类型安全性、二进制代码重用、代码的恢宏、命名约定**

  ① 、质量:空间的泛型和非泛型集合类 System.Collections 和
System.Collections.Generic

    值类型存款和储蓄在栈上,引用类型存款和储蓄在堆上。 C# 类
是援引类型,结构是值类型。
.NET很简单把值类型转换为引用类型,所以可以在急需对象(对象是援引类型)的其余地点使用值类型。例如,int
可以授予3个目的。从值类型转换为引用类型成为装箱。假使形式要求把一个对象作为参数,同时传递五个值类型,装箱操作就会活动实行。另一方面,装箱的值类型能够动用拆箱操作转换为值类型。在拆箱时,须要选用项目强制转换运算符。

  [延伸]装箱和拆箱

【装箱和拆箱】
下面可以像处理对象那样处理字面值:
    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()方法定义为须求把2个指标作为参数。

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 }

 

  二 、类型安全

   与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());//编译时错误。

 

  【扩展】

C#,  

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

 

  三 、二进制代码的录取

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());

 

  四 、命名约定

    • 泛型类型的名目用字母T 作为前缀。
    • 若果没有特殊要求,泛型类型允许选择任意类替代,且只是用了一个泛型类型,就能够用字符T作为泛型类型的名目。    
    • 1 public class List{}

      2 
      3 public class LinkedList<T>{}
      
    • 借使泛型类型有特定的渴求(例如,它必须贯彻2个接口或派生自基类),或许使用了多个或四个泛型类型,就应给泛型类型应用描述性的名目: 

    • 1 public delegate void EventHandle(object sender,TEventArgs e);
      2 
      3 public delegate TOutput Converter<TInput,TOutput>(TInput from);
      4 
      5 public class SortedList<TKey,TValue>{}
      

 

相关文章