C#2.0泛型学习--入门篇

       最近频繁的接触到泛型方面的问题,所以也不得不来学习一下了,开始主要是在MSDN的WebCast上去下载教学录象看的(李建忠老师的),本篇文章先介绍一下泛型入门方面的知识,希望能让刚开始学习泛型的朋友能够更快的入门,言归正传,首先我们来看一下泛型的基本概念:
      最显著的一点就是它参数化了类型,把类型作为参数抽象出来,从而使我们在实际的运用当中能够更好的实现代码的重复利用,同时它提供了更强的类型安全,更高的效率,不过在约束方面,它只支持显示的约束,这样在灵活性方面就显得不是那么好了.我觉得它之所以能够提供更高的效率是因为泛型在实例化的时候采用了"on-demand"的模式,即按需实例化,发生在JIT(Just In Time)编译时.
      下面来看如何定义一个泛型类,很简单,你只需要意识到一点,在这里,类型已经被参数化了:

None.gif using  System;
None.gif
using  System.Collections.Generic;
None.gif
using  System.Text;
None.gif
None.gif
namespace  GenericTest
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
class Program
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
static void Main(string[] args)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
//使用string,int来实例化Test<T,S>类
InBlock.gif
            Test<stringint> t = new Test<stringint>("SHY520",22);
InBlock.gif
InBlock.gif            
//调用泛型类中的方法
InBlock.gif
            t.SetValue();
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/**//// <summary>
InBlock.gif    
/// 定义一个泛型类,该类有两个类型参数,分别是T,S
InBlock.gif    
/// http://pw.cnblogs.com
InBlock.gif    
/// </summary>
InBlock.gif    
/// <typeparam name="T">类型参数</typeparam>
ExpandedSubBlockEnd.gif    
/// <typeparam name="S">类型参数</typeparam>

InBlock.gif    public class Test<T,S>
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
//泛型类的类型参数可用于类成员
InBlock.gif
        private T name;
InBlock.gif        
private S age;
InBlock.gif
InBlock.gif        
public Test(T Name,S Age)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
this.name = Name;
InBlock.gif            
this.age = Age;
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public void SetValue()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            Console.WriteLine(name.ToString());
InBlock.gif            Console.WriteLine(age.ToString());
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}


        上面的例子不是很恰当,目的是让初学泛型的你了解一下泛型的定义及实例化方法,如上,我们定义了一个泛型类,那么如何实现泛型类的继承呢?这里需要满足下面两点中的任何一点即可:
1、泛型类继承中,父类的类型参数已被实例化,这种情况下子类不一定必须是泛型类;
2、父类的类型参数没有被实例化,但来源于子类,也就是说父类和子类都是泛型类,并且二者有相同的类型参数;

None.gif      // 如果这样写的话,显然会报找不到类型T,S的错误
ExpandedBlockStart.gifContractedBlock.gif
     public   class  TestChild : Test < T, S >   dot.gif { }
None.gif
None.gif    
// 正确的写法应该是
ExpandedBlockStart.gifContractedBlock.gif
     public   class  TestChild : Test < string int > dot.gif { }
None.gif
ExpandedBlockStart.gifContractedBlock.gif    
public   class  TestChild < T, S >  : Test < T, S >   dot.gif { }
None.gif
ExpandedBlockStart.gifContractedBlock.gif    
public   class  TestChild < T, S >  : Test < String,  int >   dot.gif { }

接着我们来看看泛型接口,其创建以及继承规则和上面说的泛型类是一样的,看下面的代码:
None.gif      public   interface  IList < T >  
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif {
InBlock.gif        T[] GetElements();
ExpandedBlockEnd.gif    }
 
None.gif    
public   interface  IDictionary < K,V >              
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif {
InBlock.gif        
void Add(K key, V value); 
ExpandedBlockEnd.gif    }
 
None.gif
None.gif    
//  泛型接口的类型参数要么已实例化
None.gif    
//  要么来源于实现类声明的类型参数
None.gif
     class  List < T >  : IList < T > , IDictionary < int , T >  
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif        
public T[] GetElements() dot.gifreturn null; }
InBlock.gif        
public void Add(int index, T value) 
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif
ExpandedSubBlockEnd.gif        }

ExpandedBlockEnd.gif    }

None.gif

在来看一下泛型委托,首先我们定义一个类型参数为T的委托,然后在类中利用委托调用方法:
None.gif using  System;
None.gif
using  System.Collections.Generic;
None.gif
using  System.Text;
None.gif
None.gif
namespace  GenericTest
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
//定义一个委托,类型参数为T,返回值类型T
InBlock.gif    
//泛型委托支持在返回值和参数上应用类型参数
InBlock.gif
    delegate string GenericDelete<T>(T value);
InBlock.gif
InBlock.gif    
class test
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif        
static string F(int i) dot.gifreturn "SHY520"; }
ExpandedSubBlockStart.gifContractedSubBlock.gif        
static string G(string s) dot.gifreturn "SHY520"; }
InBlock.gif
InBlock.gif        
static void Main(string[] args)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            GenericDelete
<string> G1 = G;
InBlock.gif            GenericDelete
<int> G2 = new GenericDelete<int>(F);
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }
 
ExpandedBlockEnd.gif}


        我们再来看泛型方法,C#的泛型机制只支持在方法申明上包含类型参数,也即是泛型方法。特别注意的是,泛型不支持在除了方法以外的其他类/接口成员上使用类型参数,但这些成员可以被包含在泛型类型中,并且可以使用泛型类型的类型参数。还有一点需要说的就是,泛型方法可以在泛型类型中,也可以存在于非泛型类型中。下面我们分别看一下泛型类型的申明,调用,重载和覆盖。

None.gif using  System;
None.gif
using  System.Collections.Generic;
None.gif
using  System.Text;
None.gif
None.gif
namespace  GenericTest
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
class GenericClass
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
//申明一个泛型方法
InBlock.gif
        public T getvalue<T>(T t)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
return t;
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
//调用泛型方法
InBlock.gif        
//注意:在调用泛型方法时,对泛型方法的类型参数实例化
InBlock.gif
        public int useMethod()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
return this.getvalue<int>(10);
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
//重载getvalue方法
InBlock.gif
        public int getvalue(int i)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
return i;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
//下面演示覆盖
InBlock.gif    
//要注意的是,泛型方法被覆盖时,约束被默认继承,不需要重新指定约束关系
InBlock.gif
    abstract class Parent
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
public abstract K TEST<K, V>(K k, V v) where K : V;
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
InBlock.gif    
class Child : Parent
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
public override T TEST<T, S>(T t, S s)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
return t;
ExpandedSubBlockEnd.gif        }

ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif


        最后我们来看一下泛型中的约束:
        C#中的泛型只支持显示的约束,因为这样才能保证C#所要求的类型安全,但显示的约束并非时必须的,如果不加约束,泛型类型参数将只能访问System.Object类型中的公有方法。“显式约束”由where子句表达,可以指定“基类约束”,“接口约束”,“构造器约束”,“值类型/引用类型约束”共四种约束。下面的例子来源于李建忠老师的讲座PPT。
1、基类约束:

ExpandedBlockStart.gif ContractedBlock.gif      class  A  dot.gif public void F1() dot.gif{} }  
ExpandedBlockStart.gifContractedBlock.gif    
class  B  dot.gif public void F2() dot.gif{} }  
None.gif    
class  C < S,T >  
None.gif    where S: A 
//  S继承自A 
None.gif
    where T: B  //  T继承自B 
ExpandedBlockStart.gifContractedBlock.gif
     dot.gif
InBlock.gif    
// 可以在类型为S的变量上调用F1,
InBlock.gif    
// 可以在类型为T的变量上调用F2 
ExpandedBlockEnd.gif
    }
 

2、接口约束
ExpandedBlockStart.gif ContractedBlock.gif      interface  IPrintable  dot.gif void Print(); 
ExpandedBlockEnd.gif    }

ExpandedBlockStart.gifContractedBlock.gif    
interface  IComparable < T >   dot.gif int CompareTo(T v);}
ExpandedBlockStart.gifContractedBlock.gif    
interface  IKeyProvider < T >   dot.gif { T GetKey(); }
None.gif    
class  Dictionary < K,V >  
None.gif    where K: IComparable
< K >  
None.gif    where V: IPrintable, IKeyProvider
< K >  
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif
InBlock.gif    
// 可以在类型为K的变量上调用CompareTo, 
InBlock.gif    
// 可以在类型为V的变量上调用Print和GetKey 
ExpandedBlockEnd.gif
    }

3、构造器约束
ExpandedBlockStart.gif ContractedBlock.gif class  A  dot.gif public A() dot.gif{ } }  
ExpandedBlockStart.gifContractedBlock.gif
class  B  dot.gif public B(int i) dot.gif{ } }  
None.gif
class  C < T >  
None.gifwhere T : 
new () 
ExpandedBlockStart.gifContractedBlock.gif
dot.gif
InBlock.gif
//可以在其中使用T t=new T();  
ExpandedBlockEnd.gif
}
 
None.gifC
< A >  c = new  C < A > ();  // 可以,A有无参构造器
None.gif
C < B >  c = new  C < B > ();  // 错误,B没有无参构造器

4、值/引用类型约束
ExpandedBlockStart.gif ContractedBlock.gif public   struct  A  dot.gif {  }  
ExpandedBlockStart.gifContractedBlock.gif
public   class  B  dot.gif {  }  
None.gif
class  C < T >  
None.gifwhere T : 
struct  
ExpandedBlockStart.gifContractedBlock.gif
dot.gif
InBlock.gif
// T在这里面是一个值类型 
ExpandedBlockEnd.gif
}
 
None.gifC
< A >  c = new  C < A > ();  // 可以,A是一个值类型
None.gif
C < B >  c = new  C < B > ();  // 错误,B是一个引用类型


关于C#泛型入门的知识就这么多了,我也是对着李建忠老师的教学录像来学习的,初学的朋友也可以去下载录像来看:

http://www.microsoft.com/china/msdn/events/webcasts/shared/webcast/episode.aspx?newsID=1242246

学习泛型刚刚开始,希望能有高手指点,谢谢!

Email:pwei013@163.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值