为何使用泛型编程

简介: 说明:本文主要参考和修改下面的文章,向原作者致敬! http://www.hackdark.com/_NET_C_/2013/0216/3257.html 一、基础概念     .Net的类型分为两种,一种是值类型,另一种是引用类型。

说明:本文主要参考和修改下面的文章,向原作者致敬!
http://www.hackdark.com/_NET_C_/2013/0216/3257.html

一、基础概念

    .Net的类型分为两种,一种是值类型,另一种是引用类型。

    这两个类型的本质区别,值类型数据是分配在栈中,而引用类型数据分配在堆上那么如果要把一个值类型数据放到堆上,就需要装箱操作;反之,把一个放在堆上的值类型数据取出来,则需要进行拆箱操作

 

简单的装箱与拆箱操作语句:


  1. int i = 123;
  2. object obj = i;


将i将箱!

image图1、装箱


  1. if(obj is int)
  2. {
  3. int j = (int)obj; // Unboxing,这里进行了强制类型转换
  4. }


将obj拆箱!

 

image 图2、装箱与拆箱

    由图1,在栈中的值类型与在堆中的引用类型的存储方式是不一样的。所以两者相互转换的时候需要进行装、拆箱操作。

 

 

二、非泛型集合类的种种问题

1、非泛型集合类的类型转换性能差

    装箱与拆箱操作影响效率,主要有两个方面:

    一个就是对于堆的操作效率比较低;另一个就是对于堆上分配的内存资源,需要GC来回收,从而降低程序效率

 

2、类型安全问题

    当装箱与拆箱使用在集合中时,如ArrayList或者HashTable之类,把值类型放到集合中,可能会出现潜在错误。

代码一:

  1. public interface IPersonName
  2.         {
  3.             string Name { get; set; }
  4.         }


  5.         public struct SPerson : IPersonName
  6.         {
  7.             private string name;
  8.             public string Name
  9.             {
  10.                 get { return name; }
  11.                 set { name = value; }
  12.             }

  13.             public SPerson(string personName)
  14.             {
  15.                 name = personName;
  16.             }

  17.             public override string ToString()
  18.             {
  19.                 return name;
  20.             }
  21.         }

  22.         

  23.         static void Main(string[] args)
  24.         {
  25.             ArrayList arrPersons = new ArrayList();
  26.             SPerson p = new SPerson("OldName");
  27.             arrPersons.Add(p);

  28.             p = (SPerson)arrPersons[0];
  29.             p.Name = "NewName";
  30.             Console.WriteLine(((SPerson)arrPersons[0]).Name);

  31.             ((SPerson)arrPersons[0]).Name = "NewName";

  32.             //((IPersonName)arrPersons[0]).Name = "NewName";
  33.             Console.WriteLine(((IPersonName)arrPersons[0]).Name);
  34.             Console.ReadLine();
  35.         }

image


图3

报的错误是,“无法修改取消装箱转换的结果”.

    如上操作不能通过编译。为什么呢,对于“( (Person ) arrPersons[0] )”来说,是系统用一个临时变量来接收拆箱后的值类型数据,那么由于值类型是分配在栈上,那么操作是对实体操作,可是系统不允许对一个临时值类型数据进行修改操作。

上面这段话,我暂时无法很好的理解,请各位发表高见!保留住!

 

代码二:


  1. static void Main(string[] args)
  2. {
  3.     ArrayList arrPersons = new ArrayList();
  4.     SPerson p = new SPerson("OldName");
  5.     arrPersons.Add(p);
  6.     p = (SPerson)arrPersons[0];
  7.     p.Name = "NewName";

  8.     Console.WriteLine(((SPerson)arrPersons[0]).Name);
  9.     //((SPerson)arrPersons[0]).Name = "NewName";
  10.     ((IPersonName)arrPersons[0]).Name = "NewName";
  11.     Console.WriteLine(((IPersonName)arrPersons[0]).Name);
  12.     Console.ReadLine();
  13. }


image

图4

按代码二的写法,是通的。什么原因?

    产生的临时变量的类型为IPersonName,属于引用类型,那么相当于临时变量就是原对象的引用,那么对于对于它的修改会直接修改到原对象,因此是可以的。可以说这里的不同本身在于产生临时对象的类型不同,从而造成本质的区别。

 

    通过接口来改写,这样就减少了装箱和拆箱操作,同时也保证了修改的正确性。不过要注意的是,这里接口对于的是引用类型,如果接口访问的或者返回的是值类型,那么用接口虽说能实现了,但是对于装箱和拆箱操作来说,并没有减少。

 

 

 

参考文档

http://blog.csdn.net/ycyangcai/article/details/3151767

http://www.hackdark.com/_NET_C_/2013/0216/3257.html

http://www.cnblogs.com/gaobanana/archive/2010/03/04/1678312.html

http://www.cnblogs.com/gaobanana

相关文章
|
Web App开发 Python
在ModelScope中,你可以使用Python的浏览器自动化库
在ModelScope中,你可以使用Python的浏览器自动化库
159 2
|
机器学习/深度学习 数据挖掘
R语言逻辑回归模型的移动通信客户流失预测与分析
R语言逻辑回归模型的移动通信客户流失预测与分析
|
人工智能 API
【AI大模型应用开发】【LangChain系列】实战案例6:利用大模型进行文本总结的方法探索,文本Token超限怎么办?
【AI大模型应用开发】【LangChain系列】实战案例6:利用大模型进行文本总结的方法探索,文本Token超限怎么办?
1557 0
|
easyexcel
EasyExcel使用与详细说明,EasyExcel工具类(二)
EasyExcel使用与详细说明,EasyExcel工具类
1198 0
|
SQL 存储 Oracle
做到这4点,你也能学好SQL语句
做到这4点,你也能学好SQL语句
131 1
|
弹性计算 应用服务中间件 Apache
阿里云2核4G云服务器支持多少人同时在线?并发数计算?
阿里云服务器2核4G支持多少人同时在线?关于2核4G服务器的并发数取决于实际应用程序效率、公网带宽及ECS实例规格,还有2核4G云服务器公网带宽,带宽小的话很可能直接都卡到网络入口了
1176 0
阿里云2核4G云服务器支持多少人同时在线?并发数计算?
|
算法 C++ 容器
【C++】 --- STL常用算法总结(上)
【C++】 --- STL常用算法总结
81 0
C#编程-110:文件操作File静态类
C#编程-110:文件操作File静态类
191 0
C#编程-110:文件操作File静态类
|
Linux
1.9 初学者应选择哪个Linux发行版?
前面章节中,已经对几个常见的 Linux 发行版做了简单的介绍,那么对于初学者来说,选择哪个发行版的性价比更高呢?
195 0
1.9 初学者应选择哪个Linux发行版?
|
消息中间件 存储 缓存
Kafka 分区介绍
Kafka 分区介绍
329 0
Kafka 分区介绍