第十一章 泛型方法

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);//false
int [] 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);//correct
Garith<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#中不允许定义泛型的属性、事件、索引函数和操作符。

时间: 2024-11-07 04:39:48

第十一章 泛型方法的相关文章

javascript高级程序设计 第十一章--DOM扩展

javascript高级程序设计 第十一章--DOM扩展DOM最主要的扩展就是选择符API.HTML5和Element Traversal Selectors API:定义了两个方法 querySelector() 和 querySelectorAll(),能够基于CSS选择符从DOM中取得元素.querySelector()方法接收一个CSS选择符,返回该模式匹配的第一个元素,querySelectorAll()接收的参数一样,但是返回NodeList实例: matchesSelector()

c++ primer 5th 笔记:第十一章

第十一章:关联容器 笔记 1. 关联容器和顺序容器有着根本的不同:关联容器中的元素是按关键字来保存和访问的.与之相对,顺序容器中的元素是按它们在容器中的位置来顺序保存和访问的. 2. 关联容器支持高效的关键字查找和访问,两个主要的关联容器类型是map和set.map中的元素是一些关键字-值对:关键字起到索引的作用,值则表示与索引相关联的数据.set中每个元素只包含一个关键字:set支持高效的关键字查询操作--检查一个给定关键字是否在set中. 3. 当从map中提取一个元素时,会得到一个pair

zabbix专题:第十一章 zabbix proxy分布式监控配置

zabbix专题:第十一章 zabbix proxy分布式监控配置             对Linux有兴趣的朋友加入QQ群:476794643 在线交流 本文防盗链:http://zhang789.blog.51cto.co zabbix proxy分布式监控配置 zabbix proxy可以代替zabbix server检索客户端的数据,然后把数据汇报给zabbix server,并且在一定程度上分担了zabbix server的压力.zabbix proxy可以非常简便的实现了集中式.分

第十一章 执行查询算法

第十一章      执行查询算法 基本概念: 三类查找方法:线性查找.树形查找.哈希表查找 动态查找表:在查找的同时,对表做修改操作(如插入和删除),则相应的表称为动态查找表 静态查找表:与动态查找表相反 查找过程中对关键字需要执行的平均比较次数(也称平均比较长度作为衡量一个查找算法优劣的标准 平均比较长度: 其中:n是结点的个数:pi是查找第i个结点的概率.若不特别申明,认为每个结点的查找概率相等,都为1/n:ci是找到第i个结点所需进行的比较次数. 线性查找: 基本思想:从表的一端开始,顺序

Linux与云计算——第二阶段 第一十一章:代理Proxy服务器架设—Squid代理服务器正向代理和客户端配置

Linux与云计算--第二阶段Linux服务器架设 第一十一章:代理Proxy服务器架设-Squid代理服务器正向代理和客户端配置 安装Squid 安装Squid来配置代理服务器. [1] 这是一个通用的转发代理配置 [[email protected] ~]# yum -y install squid [[email protected] ~]# vi /etc/squid/squid.conf # line 26: 添加一条新的ACL acl lan src 192.168.96.0/24

第十一章 读书笔记

第十一章  Linux驱动程序中的 并发控制 并发(concurrency)指的是多个执行单元同时.并行被执行.而并发的执行单元对共享资 源〈如硬件资摞.程序中的全局变量.静态变量等〉的访问很容易导致竞态条件( race conditions). 自旋锁并不关心锁定的|临界区究竟是怎样的操作,不管是读还是写,都只允许同时只有一个执 行单元可以极取自旋锁, 即使有多个单元同时读取临界区资源也会被锁住.实际上,对于并发访问 共享资源时,多个执行单元同时读取它是不会有任何问题的.为了解决这个问题,自旋

JS复习:第十、十一章

第十章 NodeList是一种类数组对象,用于保存一组有序的节点,可以通过位置来访问这些节点,但它并不是Array实例,将其转化为数组的方法: function converToArray(nodes){ var array = null; try{ array = Array.prototype.slice.call(nodes,0); //slice方法的参数 }catch(ex){ array = new Array(); for(var i = 0,len = nodes.length

第十一章 异常,日志,断言和调试

第十一章 异常,日志,断言,调试 由于程序的错误或一些外部环境的影响造成用户数据的丢失,用户就有可能不再使用这个程序了.为了避免,应该做到以下几点: 向用户通告错误 保存所有的操作结果 允许用户以适当的形式退出程序. 11.1 处理异常 当由于出现错误而使得某些操作没有完成,程序应该: 返回到一种安全状态,并能够让用户执行一些其他命令:或者 允许用户保存所有操作的结果,以适当的方式终止程序 异常处理的任务就是将控制权从错误产生的地方转移给能够处理这种错误的处理器.程序中可能出现的错误和问题: 用

jQuery第十一章

第十一章 一.jQuery性能优化 1.使用最新版本的jQuery类库. 2.使用合适的选择器 (1)$(“#id”) :使用id来定位DOM元素是最佳提高性能的方式. (2)$(“p”) :标签选择器的性能也不错. (3)$(“.class”) :这种方法比较复杂 (4)$(“[attribute = value]”) :利用属性来定位DOM元素会使用DOM搜索的方式来达到效果. (5)$(“ : hidden”) :利用伪选择器会带来较大的性能问题. 3.缓存对象. 4.循环DOM操作. 5