首页 > 代码库 > 第十一章 泛型方法

第十一章 泛型方法

1 概述

1.1 引入泛型方法

  在某些情况下,一个类型中可能只有少数方法成员用到了类型参数,这时就未必需要将整个类型都定义成为泛型。例如在下面的代码中,泛型类GC<T>定义了一个静态方法Contain,用于判断一个元素是否存在于一个数组之中:

public class GC<T>{    //静态字段    static readonly double PI=3.14;        //方法    public static bool Contain(T[] ts,T tp)    {        foreach(T t1 in ts)        {            if(t1.Equals(tp))                return true;        }        return false;    }}

  在每次调用该方法时,需要指定该泛型类的一个封闭的构造类型:

short[] sArray = new short[] {1,3,15,255};bool b1 = GC<short>.Contain(sArray,short.MaxValue);//falseint [] iArray = new int[]{1,3,15,255,65535};bool b2=GC<int>.Contain(iArray,ushort.MaxValue);//true

  泛型类GC<T>中定义了一个静态字段PI。由于静态成员属于泛型类的构造类型所有,所以对于每一个构造类型,都为该字段分配了存储空间。

  而下面的程序将类型参数从类的定义中转移到方法的定义中,这就是泛型方法:

    class GenericsMethodSample    {        static void Main()        {            short[] sArray = new short[] { 1, 3, 15, 255 };            Console.WriteLine(C.Contain<short>(sArray, short.MaxValue));//false            int[] iArray = new int[] { 1, 3, 15, 255, 65535 };            Console.WriteLine(C.Contain<int>(iArray, ushort.MaxValue));//true        }    }    /// <summary>    /// 泛型方法类    /// </summary>    public class C    {        //静态字段        static readonly double PI = 3.14;        //泛型方法        public static bool Contain<T>(T[] ts, T tp)        {            foreach (T t1 in ts)            {                if (t1.Equals(tp))                    return true;            }            return false;        }    }

  上面程序中,两次方法的调用都是通过同一个类进行的,静态字段PI在内存中只会占用一个存储。

1.2 泛型方法的定义

  定义泛型方法也是在方法名之后将类型参数包含在一对分隔符<>中。如果有多个类型参数,则相互间用“,”号分割。之后,所定义的类型参数既可以作为方法的参数类型和返回类型,也可以用来在方法的执行代码中定义局部变量。除此之外,泛型方法的定义规则与普通方法的定义规则相同。

  如果在同一个类型中定义了多个泛型方法,它们的类型参数是互不相关的。

  如果泛型方法属于一个泛型类型,而二者又定义了相同的类型参数,那么类型参数的使用也服从“屏蔽规则”,即泛型方法中出现的类型参数属于该方法的定义,而在类型的其它成员中出现的类型参数属于类的定义。例如:

public class GArith<T>{    private T[] m_list;    public static void Swap<T>(ref T tp1,ref T tp2)    {        ...    }}

  这时为泛型类GArith<T>创建任何一个构造类型的实例,其私有有字段m_list类型都被替换为相应的封闭类型,但不会影响到泛型方法Swap<T>的参数类型。同样,指定给方法的封闭类型也和类的构造类型无关。例如:

int x=2;int y=5;GArith<string>.Swap<int>(ref x,ref y);//correctGarith<int>.Swap<string>(ref x,ref y);//error:传递类型与实际类型不同

  所以,为了提高程序的可读性,应尽量避免为泛型类型及其泛型的成员方法定义同名的类型参数。

  在泛型方法中同样可以对类型参数进行限制,限制方式和泛型类的相同

public static T Max<T>(T tp1,T tp2) where T : IComparable<T>{    if(tp1.CompareTo(tp2) > 0)        return tp1;    else        return tp2;}

  泛型方法既可以属于普通类型,也可以属于泛型类型(泛型类、泛型结构、泛型接口)。

  C#中不允许定义泛型的属性、事件、索引函数和操作符。

第十一章 泛型方法