C# 泛型编程

  感觉对于编程这个工作,我开始一直是这样认为的,还是我们现在好。比如说语言发展了,发展成更容易理解和编程了;工具也发展了,编程的时候更方便了,比如说现在的智能提示。

          但是这样理解好像有点片面了,如果不理解一个技术的发展历史就很难真正理解它。C# 泛型编程是2.0就有的,可是自己的理解还不够,特此好好总结一下。

C# 泛型及机制

         C#泛型演示

[csharp]  view plain  copy
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5.   
  6. namespace ConsoleApplication1  
  7. {  
  8.     class Program  
  9.     {  
  10.         static void Main(string[] args)  
  11.         {  
  12.             Stack<int> test = new Stack<int>();  
  13.             test.Push(10);  
  14.             Console.WriteLine(test.GetResult());  
  15.             Console.Read();  
  16.         }  
  17.     }  
  18.   
  19.     class Stack<T>   
  20.     {  
  21.         private T[] store;  
  22.         private int size;  
  23.   
  24.         public Stack()  
  25.         {  
  26.             store = new T[10];  
  27.             size = 0;  
  28.         }  
  29.   
  30.         public void Push(T x)  
  31.         {  
  32.             store[size++] = x;  
  33.         }  
  34.   
  35.         public T Pop()  
  36.         {  
  37.             return store[--size];  
  38.         }  
  39.   
  40.         public string GetResult()  
  41.         {  
  42.             return store[--size].ToString();  
  43.         }  
  44.     }  
  45. }  


        C#泛型简介

所谓泛型,即通过参数化类型来实现在同一份代码上的操作多种数据类型。泛型编程是一种编程范式,它利用“参数化类型”将类型抽象化,从而实现更为灵活的复用。

C#泛型赋予了代码更强的类型安全,更好的复用,更高的效率,更清晰的约束

        C#泛型机制简介

C#泛型能力由CLR在运行时支持,区别于C++ 的编译时模板机制,和Java的编译时“ 搽拭法” 。这使得泛型能力可以在各个支持CLR的语言之间进行无缝的互操作。

C#泛型代码在被编译为IL 代码和元数据时,采用特殊的占位符来表示泛型类型,并用专有的IL 指令支持泛型操作。而真正的泛型实例化工作以“on-demand” 的方式,发生在JIT编译时。

       C#泛型编译机制

第一轮编译时,编译器只为Stack<T>类型产生“ 泛型版” 的IL 代码与元数据——并不进行泛型类型的实例化,T在中间只充当占位符

JIT编译时,当JIT编译器第一次遇到Stack<int>时,将用int替换“ 泛型版”IL代码与元数据中的T——进行泛型类型的实例化。

CLR 为所有类型参数为“ 引用类型” 的泛型类型产生同一份代码;但如果类型参数为“ 值类型” ,对每一个不同的“ 值类型” ,CLR将为其产生一份独立的代码

        C#泛型的几个特点

如果实例化泛型类型的参数相同,那么JIT编译器会重复使用该类型,因此C#的动态泛型能力避免了C++ 静态模板可能导致的代码膨胀的问题。
•C#泛型类型携带有丰富的元数据,因此C#的泛型类型可以应用于强大的反射技术。
•C#的泛型采用“ 基类,  接口,  构造器,  值类型/引用类型” 的约束方式来实现对类型参数的 “ 显式约束” ,提高了类型安全的同时,也丧失了C++ 模板基于“ 签名” 的隐式约束所具有的高灵活性。

泛型类型

         C#泛型类与结构

[csharp]  view plain  copy
  1. class C<U, V> { }   //合法  
  2.     class D : C<stringint> { }    //合法  
  3.     class E<U, V> : C<U, V> { }     //合法  
  4.     class F<U, V> : C<stringint> { }  //合法  
  5.     //非法  
  6.     //class G : C<U, V> { };  


       C#除可单独声明泛型类型(包括类与结构)外,也可在基类中包含泛型类型的声明。但基类如果是泛型类,它的类型参数要么已实例化,要么来源于子类(同样是泛型类型)声明的类型参数。

             泛型类型的成员

[csharp]  view plain  copy
  1. class D<V>  
  2.    {  
  3.          
  4.    }  
  5.   
  6.    class C<V>  
  7.    {  
  8.        public V fi1;   //声明字段  
  9.        public D<V> f2;  //作为其它泛型类型的参数  
  10.        public C(V x)     
  11.        {  
  12.            this.fi1 = x;  
  13.        }  
  14.    }  


       泛型类型的成员可以使用泛型类型声明中的类型参数。但类型参数如果没有任何约束,则只能在该类型上使用从System.Object继承的公有成员。

       泛型接口

[csharp]  view plain  copy
  1. interface IList<T>  
  2.    {  
  3.        T[] GetElements();  
  4.    }  
  5.    interface IDictionary<K, V>  
  6.    {  
  7.        void Add(K key, V value);  
  8.    }  
  9.   
  10.    class List<T> : IList<T>,IDictionary<int,T>  
  11.    {  
  12.   
  13.        public void Add(int key, T value)  
  14.        {  
  15.            throw new NotImplementedException();  
  16.        }  
  17.   
  18.        public T[] GetElements()  
  19.        {  
  20.            throw new NotImplementedException();  
  21.        }  
  22.    }  


泛型接口的类型参数要么已实例化,  要么来源于实现类声明的类型参数。

         泛型委托

[csharp]  view plain  copy
  1. delegate bool Predicate<T>(T value);  
  2.     class X  
  3.     {  
  4.         static bool F(int i){ return true;}  
  5.         static bool G(string s) { return false; }  
  6.   
  7.         static void Main()  
  8.         {  
  9.             Predicate<string> P2 = G;  
  10.             Predicate<int> p1 = new Predicate<int>(F);  
  11.         }  
  12.     }  


泛型委托支持在委托返回值和参数上应用参数类型,这些参数类型同样可以附带合法的约束。

       泛型方法

         泛型方法简介

•C#泛型机制只支持 “在方法声明上包含类型参数”——即泛型方法
•C#泛型机制不支持在除方法外的其他成员(包括属性、事件、索引器、构造器、析构器)的声明上包含类型参数,但这些成员本身可以包含在泛型类型中,并使用泛型类型的类型参数
• 泛型方法既可以包含在泛型类型中,也可以包含在非泛型类型中

        泛型方法的声明与调用

[csharp]  view plain  copy
  1. public class Finder  
  2.    {  
  3.        //泛型方法的声明  
  4.        public static int Find<T>(T[] items, T item)  
  5.        {  
  6.            for (int i = 0; i < items.Length; i++)  
  7.            {  
  8.                if (items[i].Equals(item))  
  9.                {  
  10.                    return i;  
  11.                }  
  12.            }  
  13.            return -1;  
  14.        }  
  15.   
  16.        //泛型方法的调用  
  17.        int i = Finder.Find<int>(new int[] { 1,3,4,5,6}, 6);  
  18.    }  


     泛型方法的重载

[csharp]  view plain  copy
  1. public class MyClass  
  2.    {  
  3.        void F1<T>(T[] a,int i);  
  4.        void F1<U>(U[] a, int i);   //不可以构成重载方法  
  5.   
  6.        void F2<T>(int x);  
  7.        void F2(int x);     //可以构成重载方法  
  8.   
  9.        void F3<T>(T t) where T : A;  
  10.        void F3<T>(T t) where T : B;  
  11.    }  
  12.   
  13.    class A{}  
  14.    class B { }  


     泛型方法的重写

[csharp]  view plain  copy
  1. abstract class Base  
  2.    {  
  3.        public abstract T F<T, U>(T t, U u) where U : T;  
  4.        public abstract T G<T>(T t) where T : IComparable;  
  5.    }  
  6.   
  7.    class Derived : Base  
  8.    {  
  9.        // 合法的重写,约束被默认继承  
  10.        public override T F<T, U>(T t, U u)  
  11.        {  
  12.            throw new NotImplementedException();  
  13.        }  
  14.   
  15.        // 非法的重写,指定任何约束都是多余的  
  16.        public override T G<T>(T t) where T:IComparable  
  17.        {  
  18.            throw new NotImplementedException();  
  19.        }  
  20.    }  

       泛型约束

          泛型约束简介

•C#泛型要求对“ 所有泛型类型或泛型方法的类型参数” 的任何假定,都要基于“ 显式的约束” ,以维护C#所要求的类型安全。
•“显式约束” 由where 子句表达,可以指定“ 基类约束” ,“ 接口约束” ,“ 构造器约束” ,“ 值类型/引用类型约束” 共四种约束。
•“显式约束” 并非必须,如果没有指定“ 显式约束” ,泛型类型参数将只能访问System.Object类型中的公有方法。

          基类约束

[csharp]  view plain  copy
  1. class A{ public void F1(){} }  
  2.     class B { public void F2(){} }  
  3.     class C<S,T>  
  4.         where S:A   //S继承自A  
  5.         where T:B   //T继承自B  
  6.     {  
  7.         //可以在类型为S的变量上调用F1  
  8.         //可以在类型为T的变量上调用F2  
  9.           
  10.     }  


        接口约束

[csharp]  view plain  copy
  1. //接口约束   
  2.     interface IPrintable{void Print();}  
  3.     interface IComparable<T>{int CompareTo(T v);}  
  4.     interface IKeyProvider<T>{T GetKey();}  
  5.   
  6.     class Dictionary<K,V>  
  7.         where K:IComparable<K>  
  8.         where V:IPrintable,IKeyProvider<K>  
  9.     {  
  10.         //  可以在类型为K的变量上调用CompareTo,  
  11.         //  可以在类型为V的变量上调用Print和GetKey  
  12.     }  


      构造器约束

[csharp]  view plain  copy
  1. class A{public A(){}}  
  2.    class B{public B(int i){}}  
  3.   
  4.    class W<T> where T:new()  
  5.    {  
  6.          
  7.    }  
  8.   public class test  
  9.   {  
  10.       W<A> c=new W<A>();   //可以A有无参构造函数  
  11.       W<B> c=new W<B>();   //错误,B没有无参构造器  
  12.   }  


     值类型/引用类型约束

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值