.NET泛型解析(上)
【1】:泛型介绍
泛型是C#2.0中一个重要的新特性,泛型是CLR和编程语言提供的一种特殊机制,它支持另一种形式的代码重用。泛型通常用与集合以及作用于集合的方法一起使用,当然也可以单独使用.
一般情况下,创建泛型类的过程为:从一个现有的具体类开始,逐一将每个类型更改为类型参数,直至达到通用化和可用性的最佳平衡。 创建您自己的泛型类时,需要特别注意以下事项:
将哪些类型通用化为类型参数。
通常,能够参数化的类型越多,代码就会变得越灵活,重用性就越好。 但是,太多的通用化会使其他开发人员难以阅读或理解代码。
如果存在约束,应对类型参数应用什么约束
一条有用的规则是,应用尽可能最多的约束,但仍使您能够处理必须处理的类型。 例如,如果您知道您的泛型类仅用于引用类型,则应用类约束。 这可以防止您的类被意外地用于值类型,并允许您对 T 使用 as 运算符以及检查空值。
是否将泛型行为分解为基类和子类。
由于泛型类可以作为基类使用,此处适用的设计注意事项与非泛型类相同。 请参见本主题后面有关从泛型基类继承的规则。
是否实现一个或多个泛型接口。
例如,如果您设计一个类,该类将用于创建基于泛型的集合中的项,则可能必须实现一个接口,如 IComparable,其中 T 是您的类的类型。
【2】:泛型的表示方式
System.Collections.Generic 命名空间包含定义泛型集合的接口和类,泛型集合允许用户创建强类型集合,它能提供比非泛型强类型集合更好的类型安全性和性能。创建泛型类的过程为:从一个现有的具体类开始,逐一将每个类型更改为类型参数,直至达到通用化和可用性的最佳平衡
【3】:泛型的好处
public List<TrainingUser>GetTrainingUser(string userId)
{
DataTable dt =
SqliteHelper.ExecuteDataset(System.Data.CommandType.Text,
@"
SELECT DISTINCT UserId,TrainingId FROM TRAININGUSER AS TU
INNER JOIN [USER] AS U
ON U.ID = TU.USERID
JOIN [TRAINING] AS T
ON T.ID = TU.TRAININGID
WHERE U.ID = '"+userId+"' AND T.ENDTIME > DATETIME('now', 'localtime') AND T.StartTime <= DATETIME('now', 'localtime') ;").Tables[];
return DataTableToList(dt);
} private List<TrainingUser> DataTableToList(DataTabledt)
{
List<TrainingUser> list = new List<TrainingUser>();
if(dt. Rows.Count > )
{
foreach (DataRow row in dt .Rows)
{
TrainingUser trainingUser = new TrainingUser();
if(row["UserId" ] != null)
{
trainingUser .UserId = row["UserId"].ToString();
}
if(row["TrainingId" ] != null)
{
trainingUser.TrainingId = row["TrainingId"].ToString();
}
list.Add(trainingUser);
}
}
return list;
}
public static List<T> ToList1<T>(DataTable dt) whereT : class, new()
{
var prlist =new List<PropertyInfo>();
Type type = typeof(T);
Array.ForEach(
type.GetProperties(),
p =>
{
if(dt.Columns.IndexOf(p.Name) !=-)
{
prlist.Add(p);
}
});
var oblist = new List<T>(); // System.Data.SqlTypes.
foreach(DataRow row in dt.Rows)
{
var ob = new T();
prlist.ForEach(
p =>
{
if(row[p.Name] != DBNull.Value)
{
p.SetValue(ob, row[p.Name], null);
}
});
oblist.Add(ob);
} return oblist;
}
在上面的这个方法中,我们定义了一个泛型方法,内部实现中是使用了反射的原理,将DataTable转换为了List(反射后续随笔中总结,此处只关注泛型部分即可),我们定义了一个静态的返回值为List<T> ,前面我们说过 T : 代表任意类型(枚举除外),ToList1<T>,说明我们在调用这个方法的时候,同时要赋予方法名一个类型值,这个类型要和它的返回值类型一致(泛型是类型安全的),Where : 用于限制T的条件 ,例如 where T : class,new() 表示 T 只能是一个类,或者一个类型对象,那么我们在调用的时候就可以这样来
public List<TrainingUser>GetTrainingIdByUserId(string userId)
{
List<TrainingUser> trainingUserList = DataTableHelper.ToList1<TrainingUser>(
SqliteHelper.ExecuteDataset(System.Data.CommandType.Text,
@"
SELECT DISTINCT UserId,TrainingId FROM TRAININGUSER AS TU
INNER JOIN [USER] AS U
ON U.ID = TU.USERID
JOIN [TRAINING] AS T
ON T.ID = TU.TRAININGID
WHERE U.ID = '"+ userId +"' AND T.ENDTIME > DATETIME('now', 'localtime') AND T.StartTime <= DATETIME('now', 'localtime') ;").Tables[]);
return trainingUserList ;
}
private static void ListTest()
{
List<int>list = new List<int>();
for(inti = ; i < ; i++)
{
list.Add(i);
int a = list[i];
}
list =null;
}
private static void ArrListTest()
{
ArrayList arr = new ArrayList();
for(inti = ; i <; i++)
{
arr.Add(i);
int s = (int)arr[i];
}
arr = null;
} Stopwatch sw = new Stopwatch();
sw.Start();
ListTest();
Console.WriteLine(" 使用泛型List执行值类型方法历时 : "+ sw.Elapsed.ToString());
sw.Stop(); Stopwatch sw1 = new Stopwatch();
sw1.Start();
ArrListTest();
Console.WriteLine(" 使用非泛型ArrayList执行值类型方法历时 : "+ sw1.Elapsed.ToString());
sw1.Stop();
Console.ReadLine();
通过循环 100 来比较,结果为 :

我们可以看到非泛型的时间要比泛型的时间多出0.0000523秒,泛型比非泛型的时间要多出一些, 那么我们将数值改动一下改为循环 1000次.得出结果为 :





将一个泛型算法应用于一个具体的类型时,编译器和CLR能理解开发人员的意图,并保证只有与指定数据类型兼容的对象才能随同算法使用,若试图使用不兼容类型的一个对象,会造成编译时错误,或者运行时抛出异常
此篇至此,下篇主要知识点 :
1、泛型方法2、泛型接口3、泛型约束(主要约束,次要约束,构造器约束)4、泛型类型转型5、泛型委托6、泛型和反射7、泛型和属性
温馨提示 : 知识点重温,不断总结,思考, 也是一种阶段性提高,希望能帮到在读的你.
.NET泛型解析(上)的更多相关文章
- WCF 已知类型和泛型解析程序 KnownType
数据协定继承 已知类型和泛型解析程序 Juval Lowy 下载代码示例 自首次发布以来,Windows Communication Foundation (WCF) 开发人员便必须处理数据协定继承方 ...
- Java泛型解析(04):约束和局限性
Java泛型解析(04):约束和局限性 前两节.认识和学习了泛型的限定以及通配符.刚開始学习的人可能须要一些时间去体会到泛型程序设计的优点和力量,特别是想成为库程序猿的同学就须要下 ...
- android多线程-AsyncTask之工作原理深入解析(上)
关联文章: Android 多线程之HandlerThread 完全详解 Android 多线程之IntentService 完全详解 android多线程-AsyncTask之工作原理深入解析(上) ...
- Java泛型解析(01):认识泛型
Java泛型解析(01):认识泛型 What Java从1.0版本号到如今的8.中间Java5中发生了一个非常重要的变化,那就是泛型机制的引入.Java5引入了泛型,主要还是为了满足在199 ...
- Java泛型解析(02):通配符限定
Java泛型解析(02):通配符限定 考虑一个这种场景.计算数组中的最大元素. [code01] public class ArrayUtil { public static <T&g ...
- Java泛型解析(03):虚拟机运行泛型代码
Java泛型解析(03):虚拟机运行泛型代码 Java虚拟机是不存在泛型类型对象的,全部的对象都属于普通类,甚至在泛型实现的早起版本号中,可以将使用泛型的程序编译为在1.0虚拟机上可以执行的 ...
- 使用GSON和泛型解析约定格式的JSON串(转)
时间紧张,先记一笔,后续优化与完善. 解决的问题: 使用GSON和泛型解析约定格式的JSON串. 背景介绍: 1.使用GSON来进行JSON串与java代码的互相转换. 2.JSON的格式如下三种: ...
- js上传文件带参数,并且,返回给前台文件路径,解析上传的xml文件,存储到数据库中
ajaxfileupload.js jQuery.extend({ createUploadIframe: function(id, uri) { //create frame var frameId ...
- django 解析上传xls文件
1.解析上传数据 class DataUploadAPIView(APIView): # authentication_classes = (JSONWebTokenAuthentication, S ...
随机推荐
- 人脸识别技术大总结(1):Face Detection & Alignment
http://blog.jobbole.com/85783/ 首页 最新文章 IT 职场 前端 后端 移动端 数据库 运维 其他技术 - 导航条 - 首页 最新文章 IT 职场 前端 - Ja ...
- 基于ORB的LinearBlend融合
// L14//基于ORB实现线性融合#include "stdafx.h"#include <vector>#include <opencv2/core.hpp ...
- 通用Linux内核优化配置
通用Linux内核优化配置 针对CentOS6.CentOS7.Redhat6.Redhat7等系统 net.ipv4.ip_forward = net.ipv4.conf. net.ipv4.con ...
- CodeForces 838A Binary Blocks(前缀和)题解
题意:给你个n*m的矩阵,要求你找到一个k,k > 1,使得矩阵可以分为很多k * k的小正方形,然后进行操作把每个小正方形都变为0或1,问你怎样使操作数最小. 思路:随便暴力不可取,显然你每次 ...
- OpenDayLight Helium安装
参照:OpenDaylight的Helium(氦)版本安装 下载链接地址为 http://www.opendaylight.org/software/downloads/helium 安装: unzi ...
- 二进制文件和ASCII文件有何区别
二进制文件和ASCII文件(即文本文件)的区别,对于和计算机亲近时间尚短的同学是个难题. 1.一个例子:两种100000 有程序: #include<iostream> using nam ...
- Minimum Depth of Binary Tree,求树的最小深度
算法分析:递归和非递归两种方法. public class MinimumDepthofBinaryTree { //递归,树的最小深度,就是它左右子树的最小深度的最小值+1 public int m ...
- Cloud Native 环境
当今软件行业正发生着巨变.自上世纪50年代计算机诞生以来,软件从最初的手工作坊式的交付方式,逐渐演变成为了职业化开发.团队化开发,进而定制了软件件行业的相关规范,形成了软件产业. 今天,无论是大型企业 ...
- Java网络编程学习A轮_03_抓包分析TCP四次挥手
参考资料: http://www.jellythink.com/archives/705 示例代码: https://github.com/gordonklg/study,socket module ...
- thinkphp3.2验证码在服务器上显示不出来
ThinPHP3.2 验证码 在本地服务器访问可以显示,上传到服务器就不能访问了 /**** * 验证码 */ function code() { $config=array( 'fontSize'= ...