c#中关于泛类型(泛型)、强类型和弱类型

[泛型的概念]
(1)没有泛型的时候,所有的对象都是以object为基础,如果要使用时必须进行强制类型转换,如果对于值类型,则会导致不断拆箱装箱的过程,对系统消耗很大。
(2)使用泛型时不需要通过object类进行装箱拆箱,使用的时候都会是确定的类型。
(3)泛型的概念一开始是由集合引入,因为集合中的类型都是基于object类。可以在集合中使用泛型类。
(4)泛型不仅仅用于集合,还可以用于委托、接口和方法。
泛型的优点:高性能
ArrayList list1 = new ArrayList();
list1.Add(44); //装箱
int il1 = (int)list1[0];//拆箱
foreach (int i2 in list1)
Console.WriteLine(i2); //执行拆箱

频繁的拆箱、装箱操作在没有泛型的时候反复进行,对系统资源消耗很大。可以使用泛型集合。

List list2 = new List();
list2.Add(44); //不执行装箱
int il2 = list2[0];//不执行拆箱
foreach (int i2 in list2)
Console.WriteLine(i2); //不执行拆箱

泛型在定义的时候就区分了值类型和引用类型。

泛型的优点:类型安全
  ArrayList list = new ArrayList();
   list.Add(44);
   list.Add("mystring");
   list.Add(new MyClass());
   foreach (int i in list)
   Console.WriteLine(i);    

类型安全在于提前避免异常的出现。

List list2 = new List();
list2.Add(44);
  //list2.Add("mystring");
  //list2.Add(new MyClass());
直接编译不通过。


泛型的优点:代码的重用与扩展
List这个泛型类在使用时可以根据需要用不同的类型实例化:

List list=new List();
list.Add(44);

List stringList=new List();
stringList.Add(“mystring”);

List myclassList=new List();
myClassList.Add(new MyClass());

泛型的优点:代码的重用与扩展

定义一个泛型类:
public class aaa 注意:这里的T只是一个标识而已,定义成任何字符都可以。
   {
   public void abc(T a)
   {
   Console.WriteLine(a);
   }
   }

使用它:
   //使用string实例化
   aaa aaa = new aaa();
   aaa.abc("aaabbb");
   //使用int实例化
   aaa bbb = new aaa();
   bbb.abc(new object());
   Console.Read();
命名约定
(1)泛型类型的名称用字母T作为前缀。
(2)使用泛型时,使用,如:
Public class List {}
Public class Linkedlist{}
(3)如果泛型类型有特定的要求(例如必须实现一个派生于基类的接口),或者使用了两个或多个泛型类型,就应给泛型类型使用描述性的名称:
比如:
  public interface ccc
   { void abc(TTT arg1); }
  public class aaa:ccc
   { public void abc(TTT a)
   { Console.WriteLine(a); } }

Public class SortedList{}

泛型集合
泛型集合存在于using System.Collections.Generic下.我们主要介绍如下List ,其它的泛型集合使用请查阅MSDN。

 

 

  强类型和弱类型指的是两个具有直接或者间接继承关系的两个类。如果一个类是另一个类的直接或者间接基类,那么它为弱类型,直接或者间接子类为强类型。后续的介绍中会用到的两个类Foo和Bar先定义在这里。Bar继承自Foo。Foo是弱类型,而Bar则是强类型。

  有了强类型和弱类型的概念,我们就可以这样的定义协变和逆变:如果类型TBar是基于强类型Bar的类型,而类型TFoo是基于弱类型Foo的类型,协变就是将TBar类型的实例赋值给TFoo类型的变量,而逆变则是将TFoo类型的实例赋值给TBar类型的变量。

  委托中的协变与逆变的使用

  协变和逆变主要体现在两个地方:接口和委托,先来看看在委托中如何使用协变和逆变。现在我们定义了如下一个表示无参函数的泛型委托 Function,类型参数为函数返回值的类型。泛型参数之前添加了一个out关键字表示T是一个协变变体。那么在使用过程中,基于强类型的委托 Fucntion实例就可以赋值给基于弱类型的委托Fucntion变量。

 

[强类型弱类型]

一直说C#是强类型语言,通俗地讲,便是指C#中的“变量”在开发时的类型便是明确的:String便是String,Int32就是Int32,毫无争议。强类型的好处有很多,张嘴便可随意举上几例:

能够享受代码提示功能  
能够获得重构工具的支持  
能够在编译期发现更多错误  

 不过C#也不是“绝对”的强类型语言,因为它也有弱类型,那就是Object。我们知道Object是所有类型的最终基类,任何类型的对象都可以使用 Object来引用。可是一旦转化成Object的变量之后,代码提示便消失了;即使我们“明确”对象的确切类型,也必须通过Cast才能使用——更何况它形成了一种被“滥用”或“误用”的机会。例如一段错误代码可能会传入一个不符合约定类型的对象,那么就会造成错误。更严重的是,这样的错误可能只要在 “运行时”才能被发现,编译器对此无能为力。

如果返回值是object类型的,就称为弱类型,否则就是强类型。 
所以说,ArrayList是一个弱类型的集合,该集合中可以放置所有的数据类型。这是不很安全。
因此我们往往需要自己编写一个强类型的集合

.Net提供了一个用于编写强类型集合的基类:System.Collections.CollectionBase
该类公开了集合中常用的,但和类型无关的操作:
Count、Clear 、RemoveAt 
最最主要的是,它提供了一个protected的InnerList,该InnerList其实就是ArrayList,因此我们自己做的强类型集合,其实就是对ArrayList的包装。昨天的代码是对CollectionBase提供的protected的List操作,该List是一个IList接口实现(IList是List的返回接口),功能比InnerList弱,如果你现在把昨天的代码修改为使用InnerList,你会发现,你代码可以少写的多。InnerList返回的是ArrayList的实例对象。


除了ArrayList集合,还有:

队列Queue表示对象的先进先出集合

 1 System.Collections.Queue q = new  System.Collections.Queue();
 2 for ( int  i = 0 ;i < 5 ;i ++ )
 3 {
 4    q.Enqueue(i);
 5}

 6 System.Console.WriteLine(q.Peek());
 7 while (q.Count > 0 )
 8 {
 9    System.Console.WriteLine(q.Dequeue());
10}

11 System.Console.ReadLine();

代码运行显示
0
0
1
2
3
4
为什么有两个0呢?因为Peek 返回位于 Queue 开始处的对象后不会移除该对象。


和Queue相反的是Stack,对象的简单的后进先出集合(不是后进后出哦)
因此,代码

 1             System.Collections.Stack s  =   new  System.Collections.Stack();
 2              for  ( int  i  =   0 ; i  <   5 ; i ++ )
 3              {
 4                s.Push(i);
 5            }

 6
 7             s.Peek();
 8              while  (s.Count  >   0 )
 9              {
10                System.Console.WriteLine(s.Pop());
11            }

运行的结果是
4
3
2
1
0
集合还有一个很重要的对象:哈希表,表示键/值对的集合。这个集合就是一个两列的两维表,第一列表示key,键是不可以重复的。
你可以检查,
是否包含特定键:ContainsKey 
是否包含特定值:ContainsValue 

1             table.Add( " Hello " " HELLO " );
2             table.Add( " HELLO " " HELLO " );
3             table.Add( " hello " " HELLO " );

取值的时候,是根据键名称取值
System.Console.WriteLine(table["hello"]);


你可能感兴趣的:(c#高级编程)