泛型的优势



假设需要一个两个整形变量交换的函数,我们很快就可以嗒嗒嗒嗒的敲出下面的 Swap 函数:

 



void Swap(ref int lhs, ref int rhs)

{

    int temp = lhs;

    lhs = rhs;

    rhs = temp;

}

 

随着项目进展,我们发现,需要用到 Swap 函数的不仅是整形,变量 还有字符串,于是我们我又嗒嗒嗒嗒的重载 Swap 函数如下:

 



void Swap(ref string lhs, ref string rhs)

{

    string temp = lhs;

    lhs = rhs;

    rhs = temp;

}

 

接下来的开发中,我们又发现还有自定义的结构体,类等等等等都要用到 Swap 函数。如果我们为每一种类型都实现一个相应的 Swap 函数的话,各个版本的 Swap 函数数据类型不同外,其它完完全全一样。也就是说,项目中存在大量的代码重复。能不能之实现一个能够适用于不同数据类型的 Swap 函数,消除这种代码冗余,从而减少工作量,提高开发效率呢?

类型转换
在 C# 中 所有的类型都直接或间接的继承自 System.Object 类。换句话说,所有的类型都可以转换为 Object 类。这为我们前面的问题提供了一个解决方案——实现一个以 Object 为类型参数的 Swap 函数。其实现如下:

 



void Swap(ref object lhs, ref object rhs)

{

    object temp = lhs;

    lhs = rhs;

    rhs = temp;

}

 

调用的代码如下:



//a, b 为要传入 Swap 函数的变量

object objA = a;

object objB = b;

 

Swap(ref objA, ref objB);

 

//T 为变量 a 和 b 的数据类型

a = (T)objA;

b = (T)objB;

 

这一实现利用类型转换有效的重用了 Swap 的代码,但有两点不足。

 

首先是性能问题。每次调用 Swap 函数前,需要对其参数进行一次向上的转型;调用完之后,又要对其进行一次向下的转型。如果需要多次调用 Swap 函数(比如在一个很大的循环中),转型带来的开销是想当可观的,特别是当参数为值类型的时候。

 

第二是,无法提供编译时类型检查。下面的例子虽然能通过编译,但运行时会出现异常:

 



string a  = “This is a string”;

int b = 0;

 

object objA = a;

object objB = b;

 

Swap(ref objA, ref objB);               //可以编译

 

a = (string)objA;               //出现运行时异常

b = (ing)objB;

 

针对以上两点不足,C# 2.0 提出了泛型。

泛型
泛型是C# 2.0 提供的延迟类和函数中数据类型的定义,直到客户代码声明或实例化该数据类型。

 

泛型版的 Swap 函数实现如下

 



void Swap<T>(ref T lhs, ref T rhs)

{

    T temp = lhs;

    lhs = rhs;

    rhs = temp;

}         

 
泛型集合中的 <T>是obj类型
上例中的类型参数 T 可以实例化为任意数据类型。相对于通过类型转换重用 Swap 函数,它且不需要类型转换,有效的提高性能。而且,它还能提供编译时类型检查。调用语法与普通函数调用完全一样。

泛型的优势
从上面例子可以看出,使用泛型具有如下三点优势:

 

?       避免重复代码,最大化代码重用

?       避免无谓的类型转换,提高性能

?       提供编译时类型检查,具有类型安全性

C# code

// 在三角符号里写入类型参数T
public class GenericList<T>
{
// Node为非泛型类,作为GenericList<T>的嵌套类
private class Node
{
// 在非泛型构造函数中使用T
public Node(T t)
{
next
= null;
data
= t;
}

private Node next;
public Node Next
{
get { return next; }
set { next = value; }
}

// T作为私有成员的数据类型
private T data;

// T作为属性的返回类型
public T Data
{
get { return data; }
set { data = value; }
}
}

private Node head;

// 构造函数
public GenericList()
{
head
= null;
}

// T 作为方法的参数类型
public void AddHead(T t)
{
Node n
= new Node(t);
n.Next
= head;
head
= n;
}

public IEnumerator<T> GetEnumerator()
{
Node current
= head;

while (current != null)
{
yield return current.Data;
current
= current.Next;
}
}
}




下面的代码示例演示客户端代码如何使用泛型 GenericList <T> 类来创建整数列表。只需更改类型参数,即可方便地修改下面的代码示例,创建字符串或任何其他自定义类型的列表:

C# code

class TestGenericList
{
static void Main()
{
// int 是类型变量
GenericList<int> list = new GenericList<int>();

for (int x = 0; x < 10; x++)
{
list.AddHead(x);
}

foreach (int i in list)
{
System.Console.Write(i
+ " ");
}
System.Console.WriteLine(
"\n完成");
}
}

泛型也在用在类里,可以对参数进行约束而对于new约束而言有点特殊


public class Dictionary<K,V> where K: IComparable
ExpandedBlockStart.gifContractedBlock.gif
{
    
public void Add(K key, V value)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        
ExpandedSubBlockStart.gifContractedSubBlock.gif        
if (key.CompareTo(x) < 0{}
        
    }

}


这样就保证了任何为K类型参数提供的类型都实现了IComparable接口。所以我们的key就可以使用CompareTo方法了。

如果我们在使用时提供了没有实现IComparable接口的类型,就会出现编译时错误。

对于new()约束,大家可能有一个误解,以为使用了new约束之后,在创建对象时与非泛型的版本是一致的:

publicclassTester<T>
whereT:new()
{
publicTester()
{
t=newT();//等同于非泛型版本的new?例如objecto=newobject();?
}

privateTt;

}
  事实上,使用new关键字的作用只是让编译器在泛型实例化之处,检查所绑定的泛型参数是否具有无参构造函数:

Tester<SomeType>t=newTester<SomeType>();
//此处编译器会检查SomeType是否具有无参构造函数。若没有则会有compileerror

 

转载于:https://www.cnblogs.com/dewin/archive/2009/06/28/1512868.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/381299.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

系统分析师资料_如何成为一名数据分析师?

随着大数据的逐渐普及&#xff0c;数据分析越来越普遍应用到各个职能岗位&#xff0c;也就是说&#xff0c;不论你在哪个行业&#xff0c;都会需要数据分析技能。数据岗位的薪资水涨船高&#xff0c;成为目前最有潜力的职业选择之一。根据猎聘发布《猎聘2019年中国AI&大数据…

设置文本区域大小_数据验证基本设置技巧

数据验证可以规范用户的文本及数字输入格式&#xff0c;如只能输入指定区间的数值、只能输入文本数据、限制输入空格、限制输入重复值等。设置了数据验证条件后&#xff0c;对符合条件的数据允许输入&#xff0c;对不符合条件的数据则禁止输入。因此&#xff0c;利用此设置可以…

mysql5.7修改root密码_七小服公开课EMC isilon修改丢失的root密码

1、连接串口&#xff0c;并重启2、在终端上&#xff0c;当引导过程中看到如下提示符时&#xff0c;按下空格键:Hit [Enter] to boot immediately, or any other key for command prompt.3、在OK提示符下&#xff0c;运行以下命令:boot -s4、看到 "Enter full pathname of …

服务器php只显示文本,服务器上的php echos文件是文本而不是二进制文件

我编写了一个PHP页面,它读取一个文件,并在添加了一些头文件后对其进行回显:header(Content-disposition: filename" . $fname . ");header(Pragma: no-cache);header(Expires: 0);header(Cache-Control: must-revalidate, post-check0, pre-check0);header(Pragma: p…

vc 6.0 显示文件全路径_配送路径规划思考(十二)

前面十一集的链接配送路径规划思考(十一)配送路径规划思考(十)配送路径规划思考(九)配送路径规划思考(八)配送路径规划思考(七)配送路径规划思考(六)配送路径规划思考(五)配送路径规划思考(四)配送路径规划思考(三)配送路径规划思考(二)配送最短路径思考(一)思考(十一)分享了政…

怎么暂时关闭网站php,WordPress怎么临时关闭网站进行维护

有时可能会因为各种原因导致我们的网站出现访问错误&#xff0c;此时我们就需要临时关闭站点进行维护&#xff0c;那么我们该如何临时关闭站点进行维护呢&#xff1f;下面让我们来看一下如何临时关闭我们的站点吧。1、.maintenance法在WordPress根目录下新建一个名为.maintenan…

DataList控件分页

实现了对DataList的分页 HTML控件的值需要转换web应用程序就可以取到了 1 /**//// <summary> 2 /// 当前页数 3 /// </summary> 4 int CurrentPage; 5 /**//// <summary> 6 /// 每页条数 7 /// </summa…

现代php 阅读笔记,PHP 手册阅读笔记 - 语言参考篇

最近计划把 PHP手册&#xff0c;认真的先过一遍。记录一些以前不知道&#xff0c;不明确的知识。语言参考 > 类型【新认知】强制转换类型用 settype( mixed $var, string $type )。判断变量的类型用is_type函数。例如&#xff1a;if (is_int($an_int)) {$an_int 4;}if (is_…

mongodb连接失败_mongodb 数据库及数据分页

本文转载于 SegmentFault 社区作者&#xff1a;小小蚊子在做自己的一个小项目时&#xff0c;新学习了 mongodb非关系型数据库&#xff0c;使用了 mongoose封装好的查询方法&#xff0c;包括数据库分页用到的limit和 skip 方法&#xff0c;这里记录下。一mongodb 数据库连接参照…

mysql 关联查询_Mysql查询优化器,再也不会因为该什么时候建立索引发愁了

优化器的作用&#xff1a;我们知道&#xff0c;一条SQL语句&#xff0c;可以有很多执行方式&#xff0c;最后都返回相同的结果&#xff0c;而优化器的作用就是找到最好的执行计划。一、RBO-基于规则的优化器(rule)系统内置的一套硬编码规则&#xff0c;根据规则生成执行计划&am…

购物车的收货地址js php,Javascript实现购物车功能的详细代码

我们肯定都很熟悉商品购物车这一功能&#xff0c;每当我们在某宝某东上购买商品的时候&#xff0c;看中了哪件商品&#xff0c;就会加入购物车中&#xff0c;最后结算。购物车这一功能&#xff0c;方便消费者对商品进行管理&#xff0c;可以添加商品&#xff0c;删除商品&#…

CLI下的网页浏览器之二——Lynx

出自&#xff1a;http://vb2005xu.javaeye.com/blog/230044 Lynx浏览器使用指南 Lynx是一个字符界面下的全功能的WWW浏览器。Lynx 可以运行在很多种操作系统下&#xff0c;如VMS, UNIX, Windows 95, Windows NT等&#xff0c;当然也包括Linux。 由于没有漂亮的图形界面&#xf…

stm32 整数加法循环时间_【教学设计】小数加法教学设计

小数加法教学设计刘秀锦舞钢市特殊教育学校教材分析本节课是第四单元“小数加减法”的第一课时&#xff0c;小数加减法是以整数加减法为基础进行教学的&#xff0c;本节课走踏实了&#xff0c;后边的知识才能顺利的进行下去&#xff0c;所以本节课还是以小步走、学一点、练一点…

天锐绿盾解密_天锐绿盾数据防泄密系统

天锐绿盾数据防泄密系统&#xff08;简称数据防泄密系统&#xff09;是一套从源头上保障数据安全和使用安全的软件系统。包含了文件透明加解密、内部文件流转、密级管控、离线管理、文件外发管理、灵活的审批流程、工作模式切换、服务器白名单等功能&#xff0c;并全面覆盖Mac、…

矩阵维度必须一致_如何从看得懂到会使用矩阵思维

本来我一开始是想学习如何使用艾森豪威尔矩阵的&#xff0c;但是利用学习观的方法想去网上找有关艾森豪威尔矩阵的例子时&#xff0c;发现网上几乎没有&#xff0c;网上能搜出来的都是对这个矩阵的介绍&#xff0c;看完这些介绍你会发现很简单&#xff0c;都能看懂&#xff0c;…

numpy 归一化_归一化(MinMax)和标准化(Standard)的区别

此文参考https://blog.csdn.net/u010947534/article/details/86632819定义上的区别归一化&#xff1a;将数据的值压缩到0到1之间&#xff0c;公式如下标准化&#xff1a;将数据所防伪均值是0&#xff0c;方差为1的状态&#xff0c;公式如下&#xff1a;归一化、标准化的好处&am…

python多态_Python基础入门18节-第十六节 面向对象如何理解多态

多态是面向对象的一大特性&#xff0c;Python本身也是一门多态性的语言。在Python中要实现多态&#xff0c;还是得借助于上节提到的继承。假设有这么一个场景&#xff0c;在夏季我们可以看到荷花、牡丹花、太阳花&#xff0c;夏天一到这些花全都开放了。这些花我们就将它理解多…

linux重启后root密码错误,Linux技巧| 解决Debian Root密码忘记的问题

Debian Root密码忘记开机 grub 菜单下进入单用户模式进行修改密码/修改系统文件。解决过程注&#xff1a;本教程适用于 Debian 7 8 91. 首先。重启一下系统。在开机 grub 内核选择菜单那里&#xff0c;迅速按“e”。2. 将光标移动到“linux”开头的那一行&#xff0c;将原来的“…

SilverLight学习笔记--Silverlight中WebService通讯

本文我们学习如何在Silverlight中使用WebService进行通讯。 新建项目Silverlight应用程序&#xff0c;命名为&#xff1a;SLWebService。在服务器端我们需要做两项目工作: 1、在Web项目中新建一个类Person&#xff0c;我们将在WebService中返回它的实例化对象。Person类定义如下…

导出文件_一招解决PDF文件导出图片

将PDF文件保存为高清图片是经常需要进行的保存方式之一&#xff0c;因为PDF文件虽然安全性高&#xff0c;但是相比较图片而言&#xff0c;还是不易进行查看的&#xff0c;那么如何将PDF文件导出图片呢&#xff1f;以前也了解过很多方法&#xff0c;不过最好的当然不是截图了。虽…