泛型系列3:获取泛型的类型
4.3 获取泛型的类型
问题
您需要在运行时获得一个泛型类型实例的Type对象。
解决方案
在使用typeof操作符时提供类型参数;使用类型参数实例化的泛型类型,用GetType()方法。
声明一个一般类型和一个泛型类型如下:
public class Simple
{
public Simple()
{
}
}
public class SimpleGeneric<T>
{
public SimpleGeneric()
{
}
}
使用typeof操作符和简单类型的名称就可以在运行时获得简单类型的类型。对于泛型类型来说,在调用typeof时类型参数必须要提供,但是简单类型实例和泛型类型实例都可以使用相同的方式来调用GetType()。
Simple s = new Simple();
Type t = typeof(Simple);
Type alsoT = s.GetType();
//提供类型参数就才可以获得类型实例
Type gtInt = typeof(SimpleGeneric<int>);
Type gtBool = typeof(SimpleGeneric<bool>);
Type gtString = typeof(SimpleGeneric<string>);
// 当有一个泛型类实例时,您也可以使用GetType的旧的方式去调用一个实例。.
SimpleGeneric<int> sgI = new SimpleGeneric<int>();
Type alsoGT = sgI.GetType();
讨论
不能直接获取泛型类的类型,因为如果不提供一个类型参数,泛型类将没有类型(参考秘诀4.2获得更多信息)。只有通过类型参数实例化的泛型类才有Type。
如果您在使用typeof操作符时,只提供泛型类型定义而不提供类型参数,将得到下面的错误:
// 这产生一个错误:
// Error 26 Using the generic type 'CSharpRecipes.Generics.SimpleGeneric<T>'
// requires '1' type arguments
Type gt = typeof(SimpleGeneric);
阅读参考
查看秘诀4.2;参考MSDN文档中的“typeof”主题。
4.4 使用相应的泛型版本替换ArrayList
问题
您希望通过将所有ArrayList对象替换为相应的泛型版本以提高应用程序的效率,并使得代码更易于使用。当结构体或其他值类型存储在这些数据结构中时,会导致装箱/拆箱操作,这时就需要这么做。
解决方案
使用更有效率的泛型类System.Collections.Generic.List来替换已存在的System.Collection.ArrayList类。
下面是使用System.Collection.ArrayList对象的简单例子:
public static void UseNonGenericArrayList()
{
// 创建一个ArrayList.
ArrayList numbers = new ArrayList();
numbers.Add(1); // 导致装箱操作
numbers.Add(2); // 导致装箱操作
// 显示ArrayList内的所有整数
// 每次迭代都导致拆箱操作
foreach (int i in numbers)
{
Console.WriteLine(i);
}
numbers.Clear();
}
相同的代码使用了System.Collections.Generic.List对象
public static void UseGenericList()
{
// 创建一个List.
List<int> numbers = new List<int>();
numbers.Add(1);
numbers.Add(2);
// 显示List中的所有整数.
foreach (int i in numbers)
{
Console.WriteLine(i);
}
numbers.Clear();
}
讨论
因为所有的应用程序几乎都会使用ArrayList,从提升您的应用程序的执行效率开始是一个不错的选择。对于应用程序中简单使用ArrayList的地方来说,这种替代是非常容易的。但有些地方需要注意,例如,泛型List类未实现Icloneable接口而ArrayList实现了它。
表4-1显示了两个类中的等价成员。
ArrayList类成员 |
等价的泛型List类成员 |
Capacity 属性 |
Capacity属性 |
Count属性 |
Count属性 |
IsFixedSize属性 |
((IList)myList).IsFixedSize |
IsReadOnly属性 |
((IList)myList).IsReadOnly |
IsSynchronized属性 |
((IList)myList).IsSynchronized |
Item属性 |
Item属性 |
SyncRoot属性 |
((IList)myList).SyncRoot |
Adapter 静态方法 |
N/A |
Add 方法 |
Add方法 |
AddRange方法 |
AddRange方法 |
N/A |
AsReadOnly方法 |
BinarySearch方法 |
BinarySearch方法 |
Clear方法 |
Clear方法 |
Clone方法 |
Getrange(0, numbers.Count) |
Contains方法 |
Contains方法 |
N/A |
ConvertAll方法 |
CopyTo方法 |
CopyTo方法 |
N/A |
Exists方法 |
N/A |
Find方法 |
N/A |
FindAll方法 |
N/A |
FindIndex方法 |
N/A |
FindLast方法 |
N/A |
FindLastIndex方法 |
N/A |
ForEach方法 |
FixedSize 静态方法 |
N/A |
Getrange方法 |
Getrange方法 |
IndexOf方法 |
IndexOf方法 |
Insert方法 |
Insert方法 |
InsertRange方法 |
InsertRange方法 |
LastIndexOf方法 |
LastIndexOf方法 |
ReadOnly 静态方法 |
AsReadOnly方法 |
Remove方法 |
Remove方法 |
N/A |
RemoveAll方法 |
RemoveAt方法 |
RemoveAt方法 |
RemoveRange方法 |
RemoveRange方法 |
Repeat 静态方法 |
使用for循环和Add方法 |
Reverse方法 |
Reverse方法 |
SetRange方法 |
InsertRange方法 |
Sort方法 |
Sort方法 |
Synchronized 静态方法 |
lock(myList.SyncRoot) {…} |
ToArray方法 |
ToArray方法 |
N/A |
trimExcess方法 |
TRimToSize方法 |
trimToSize方法 |
N/A |
trueForAll方法 |
表4-1中的几个ArrayList的成员和泛型List的成员并非一一对应。从属性开始说,只有Capacity,Count和Item属性两个类中都存在。为了弥补List类中的几个缺失的属性,可以把它显式转换为Ilist接口。下面的代码演示了如何使用这些显式转换以获得缺失的属性。
List<int> numbers = new List<int>();
Console.WriteLine(((IList)numbers).IsReadOnly);
Console.WriteLine(((IList)numbers).IsFixedSize);
Console.WriteLine(((IList)numbers).IsSynchronized);
Console.WriteLine(((IList)numbers).SyncRoot);
注意,由于缺少返回同步版本的泛型List代码和缺少返回固定尺寸的泛型List代码,IsFixedSize和IsSynchronized属性将总是返回false。SyncRoot属性被调用时将总是返回相同的对象,本质上这个属性返回this指针。微软已经决定从所有泛型集合类中去除创建同步成员的功能。做为代替,他们推荐使用lock关键字去锁住整个集合或其他类型的同步对象来满足您的需要。
静态的ArrayList.Repeat在泛型List中没有对应的方法。做为代替,您可以使用下面的泛型方法:
public static void Repeat<T>(List<T> list, T obj, int count)
{
if (count < 0)
{
throw (new ArgumentException(
"参数count 必须大于或等于零"));
}
for (int index = 0; index < count; index++)
{
list.Add(obj);
}
}
这个泛型方法有三个参数:
list
泛型List对象
obj
将被以指定次数添加进泛型List中的对象
count
把obj添加进泛型类中的次数
因为Clone方法也没有出现在泛型List类中(因为这个类并没有实现Icloneable接口),您可以使用泛型List类的GetRange方法做为替代。
List<int> oldList = new List<int>();
// 给oldList添加元素…
List<int> newList = oldList.GetRange(0, oldList.Count);
GetRange方法对List对象中一个范围的元素执行浅拷贝(跟ArrayList中的Clone方法接近)。在此例中这个范围是所有元素。
提示:ArrayList默认的初始容量是16个元素,而List<T>的默认初始容量为4个元素。这意味着当添加第17个元素时,List<T>不得不改变尺寸(重新分配内存)3次,而ArrayList只重新分配一次。这一点在评估应用程序性能时需要被考虑。
转载于:https://www.cnblogs.com/kakaliush/archive/2011/11/30/2269811.html
泛型系列3:获取泛型的类型相关推荐
- java 反射和泛型-反射来获取泛型信息
通过指定对应的Class对象,程序可以获得该类里面所有的Field,不管该Field使用private 方法public.获得Field对象后都可以使用getType()来获取其类型. Class&l ...
- java8泛型包括_JAVA8 获取泛型类型问题
函数式编程 最开始的版本忘记了接口的情况-publicclassEEE{publicstaticvoidmain(String[]args){Listtypes=newArrayList();find ...
- java 获取泛型的type,如何获取泛型的Type类型
开发中很多时候都遇到或使用到泛型.例如在json转换成bean对象或其他对象,而对象中存在泛型,这时候需要用到TypeToken. Type:是java里的 java.lang.reflect.Typ ...
- Java获取泛型T的类型 T.class
import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type;public class Main{public s ...
- [转载] Java获取泛型T的类型 T.class
参考链接: Java中的抽象 import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; public cla ...
- android 无线接口 泛收,Android下的Java之interface接口泛型 动态获取泛型的类型
Android的泛型有多坑? 先来看看该问题的场景 将String转换成具体对象时,需要进行的关键点就是获取到对象的类型 // 这里定义了一个泛型R,那运行时如何获取到这个类型呢? // 第一眼看上去 ...
- java获取泛型的类型_Java反射获取泛型类型
public class Person{ }importjava.lang.reflect.ParameterizedType;importjava.lang.reflect.Type;public ...
- java 运行时获取泛型真实类型
前情提要 本文章用于运行时获取泛型的具体类型,有一些情况下可以获取到真实类型,有一些情况下获取不到的情况. Class 类的两个方法 /*** Returns the {@code Class} re ...
- 【转】Java获取泛型T的具体类型
在日常的开发中特别是框架的设计或者实用反射的时候,经常会实用class类去做一些事情,但是由于系统的抽象等问题,经常实用泛型去做一些事情.所以如何在泛型中获取具体的class类呢? 解决方案:父类本身 ...
最新文章
- 医疗人工智能会替代医生吗
- python输入一个数组输出24进制式的时间_【翻译】《利用Python进行数据分析·第2版》第4章(下)NumPy基础:数组和矢量计算...
- ios设计规范_e微课5期:ios设计规范带来的设计细节(下篇)
- WPF DataGrid 对行中单元格的访问
- POST请求传递参数(十一)
- Spring MVC异常处理详解 ExceptionHandler good
- 解决fullgc_CMS发生FullGc分析
- 处理数据类型转换,数制转换、编码转换相关的类
- Tkinter模拟发送邮箱验证码并在指定时间后验证码过期
- java 文件上传到服务器_Java上传文件到服务器端的方法
- matlab的火山图,如何用EXCEL画一张帅气的火山图?
- SolidWorks 2010 SP0.0 最新下载+序列号 注册机及方法
- kangle安装php7.0_搭建Kangle+EasyPanel对接SWAP IDC虚拟主机自助开通完整教程
- 用什么工具可以批量查询韵达快递
- uniapp canvas绘图生成海报
- STM32例程分享-01-OLED模块(IIC)
- AspectJ 学习笔记
- js获取当前时间、获取未来多少天的时间、获取星期、获取某一天的年月方法
- 魔力宝贝道具服务器无响应,魔力宝贝:关于道具服务器第一天的感想
- Label mx条码标签打印软件生成跳号的流水号
热门文章
- 一个代表年月的类YearMonth
- Asp.net页面之间传递参数的几种方法
- java 正则表达式 中文数字和字母_Java中过滤出字母、数字和中文的正则表达式...
- (92)FPGA模块例化传递参数(parameter)
- (14)Verilog HDL参数:parameter
- 1013.clion配置快捷提示模板
- VS Code调试C代码
- java c 面向对象比较教程_c语言初学指针,对于java面向对象的初理解
- qt5中重绘工具栏_Qt ------ QPainter 和控件组件的重绘
- 人工智能python基础知识_AI 人工智能基础知识-习题