.NET泛型01,为什么需要泛型,泛型基本语法
.NET泛型或许是借鉴于C++泛型模版,借助它可以实现对类型的抽象化、泛型处理,实现了类型和方法之间的解耦。一个最经典的运用是在三层架构中,针对不同的领域模型,在基接口、基类中实现针对各个领域模型的泛型处理。
本篇主要包括:
■ 为什么需要泛型
※ 不用泛型
※ 使用泛型
※ 泛型的运行时本质
■ 泛型语法
■ 典型的泛型类
为什么需要泛型
不用泛型
来看一个比较类型的方法。
public class Calculator
{
public static bool AreEqual(int value1, int value2)
{
return value1 == value2;
}
}
在客户端调用。
class Program
{
static void Main(string[] args)
{
bool result = Calculator.AreEqual(1, 2);
if (result)
{
Console.WriteLine("相等");
}
else
{
Console.WriteLine("不等");
}
Console.ReadKey();
}
}
运行结果:不等
不用泛型的缺点一:不是类型安全
如果我们想使用现在的方法来比较字符串类型。
bool result = Calculator.AreEqual("A", "B");
这时,看到编译器报错。从这点来看,AreEqual()方法不是类型安全的方法,当输入string类型,编译器就会报错。
如果把AreEqual()方法的参数类型改成object,编译器就不再报错。
public class Calculator
{
public static bool AreEqual(object value1, object value2)
{
return value1 == value2;
}
}
以上,运行也正常。
不用泛型的缺点二:装箱与拆箱导致性能降低
现在,对于AreEqual(object value1, object value2),从方法本身来讲是没有问题的,但在客户端调用的时候,比如我们还是想比较值类型。
bool result = Calculator.AreEqual(1, 2);
在运行时,当整型值类型参数1和2传递、赋值给AreEqual(object value1, object value2)中的引用类型参数value1和value2的时候,发生了一次"装箱"操作。而当把引用类型转换成值类型的时候,又会发生一次"拆箱"操作,这导致性能的降低。
使用泛型
把AreEqual()改成泛型方法。
public class Calculator
{
public static bool AreEqual<T>(T value1, T value2)
{
return value1.Equals(value2);
}
}
于是,在客户端可以这样:
bool result = Calculator.AreEqual<string>("A", "A");
bool result = Calculator.AreEqual<int>(5, 3);
由此,使用泛型的好处有:
1、实现了方法和类型的解耦。
2、不会造成类型转换,规避了因装箱于拆箱引起的性能问题。
3、泛型保证了类型的绝对安全。
当然,还可以把T的位置放在类上:
public class Calculator<T>
{
public static bool AreEqual(T value1, T value2)
{
return value1.Equals(value2);
}
}
然后这样使用:
bool result = Calculator<string>.AreEqual("A", "A");
bool result = Calculator<int.AreEqual(1, 2);
泛型的运行时本质
CLR中有专门的IL指令支持泛型操作。
→初次编译时,生成IL代码和元数据,T只是类型占位符,在编译时不进行实例化
→JIT编译时,以实际类型替换元数据中的T占位符
→将元数据转换为本地代码
泛型语法
class MyArray<T> where T : Student, new()
{
private T[] _items;
public T myData; public MyArray()
{
myData = default(T);
} public void Add(T item)
{}
}
创建泛型实例要指定实际的数据类型:
MyArray<Int32> myArr = new MyArray<Int32>();
值类型的默认值为0,引用类型的默认值为null,使用泛型默认值:
myData = default(T);
泛型约束:
T : 基类名,表示必须是基类名的派生类
T :new(), 表示必须具有无参构造函数,new()约束必须放在最后面
T :struct, 表示必须是值类型
T :class, 表示必须是引用类型
T :接口名,表示必须实现该接口,或实现该接口的接口
泛型类本质上仍然是一个类,依然可以继承:
internal class GenericeComparer<T> : Comparer<T> where T : IComparable<T>
class MyArray<T> : ArrayList
典型的泛型类
在System.Collections.Generic命名空间和System.Collections.ObjectModel中,定义了不同的泛型类和泛型接口,这些泛型多为集合类。
List<T> 对应ArrayList集合类
SortedList<TKey, TValue> 对应SortedList集合类
Queue<T> 先进先出的集合类
Stack<T> 后进先出的集合类
Collection<T> 自定义泛型集合的基类
Dictionary<TKey, TValue> 对应于Hashtable集合类
参考资料:
《你必须知道的.NET(第2版)》,作者王涛。
".NET泛型"系列包括:
.NET泛型01,为什么需要泛型,泛型基本语法
.NET泛型02,泛型的使用
.NET泛型03,泛型类型的转换,协变和逆变
.NET泛型04,使用Lazy<T>实现延迟加载
.NET泛型01,为什么需要泛型,泛型基本语法的更多相关文章
- [C# 基础知识梳理系列]专题六:泛型基础篇——为什么引入泛型
引言: 前面专题主要介绍了C#1中的2个核心特性——委托和事件,然而在C# 2.0中又引入一个很重要的特性,它就是泛型,大家在平常的操作中肯定会经常碰到并使用它,如果你对于它的一些相关特性还不是很了解 ...
- 对比两个同类型的泛型集合并返回差异泛型集合 ——两个List<类名>的比较
1: /// <summary> 2: /// 对比两个同类型的泛型集合并返回差异泛型集合 3: /// </summary> 4: /// <typeparam nam ...
- java 泛型详解(普通泛型、 通配符、 泛型接口)
java 泛型详解(普通泛型. 通配符. 泛型接口) JDK1.5 令我们期待很久,可是当他发布的时候却更换版本号为5.0.这说明Java已经有大幅度的变化.本文将讲解JDK5.0支持的新功能---- ...
- 3. Java面向对象之泛型-指定多个泛型
3. Java面向对象之泛型-指定多个泛型 package generic; class MutiGeneric<K, T> { private K key; private T take ...
- java泛型基础、子类泛型不能转换成父类泛型
参考http://how2j.cn/k/generic/generic-generic/373.html 1.使用泛型的好处:泛型的用法是在容器后面添加<Type>Type可以是类,抽象类 ...
- java泛型(二)、泛型的内部原理:类型擦除以及类型擦除带来的问题
微信公众号[程序员江湖] 作者黄小斜,斜杠青年,某985硕士,阿里 Java 研发工程师,于 2018 年秋招拿到 BAT 头条.网易.滴滴等 8 个大厂 offer,目前致力于分享这几年的学习经验. ...
- java泛型基础、子类泛型不能转换成父类泛型--未完待续
参考http://how2j.cn/k/generic/generic-generic/373.html 1.使用泛型的好处:泛型的用法是在容器后面添加<Type>Type可以是类,抽象类 ...
- 泛型 System.Collections.Generic及泛型继承、运算符、结构、接口、方法、委托、事件、可空类型等
一.定义泛型类 void Main() { //实例化泛型类时,才指定具体的类型 MyGenericClass<); Console.WriteLine(MyGeneri.InnerT1Obje ...
- java数据类型:集合存储元素类型限制<泛型> ;自定义类指定泛型<T> 以及限制用法;派生子类泛型<T> super(泛型内参数); 泛型通配符?以及?限制用法
问题背景 Java 集合有个缺点,把一个对象"丢进"集合里之后,集合就会"忘记"这个对象的数据类型,当再次取出该对象时 该对象的编译类型就变Object类型(其 ...
随机推荐
- Codeforces 429B Working out(递推DP)
题目链接:http://codeforces.com/problemset/problem/429/B 题目大意:两个人(假设为A,B),打算健身,有N行M列个房间,每个房间能消耗Map[i][j]的 ...
- Luogu P2069 【松鼠吃果子】
推荐一波数组模拟链表的讲解 这道题呢,数组写的话不好删除(因为后面要接过来),自然想到链表 对于一个果子,我们可以维护其前驱和后继,我们不妨记与一个点相邻的上面的点为其前驱,下面的点为其后继 观察到题 ...
- JAVA复习笔记分布式篇:kafka
前言:第一次使用消息队列是在实在前年的时候,那时候还不了解kafka,用的是阿里的rocket_mq,当时觉得挺好用的,后来听原阿里的同事说rocket_mq是他们看来kafka的源码后自己开发了一套 ...
- 关于SQLserver的索引的一些脚本
--判断无用的索引: SELECT TOP 30 DB_NAME() AS DatabaseName , '[' + SCHEMA_NAME(o.Schema_ID) + ']' + '.' + '[ ...
- poj 2369(置换群)
Permutations Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 3041 Accepted: 1641 Desc ...
- SSIS 学习之旅 序章 和 简介
SSIS 学习之旅目录: 第一章: SSIS 学习之旅 第一个SSIS 示例(一) 第二章: SSIS 学习之旅 第一个SSIS 示例(二) 第三章: SSIS 学习之旅 数据同步 第四章: SSIS ...
- 按书上学写测试pytest
慢慢的,这块知识也补好吧. 系统的学习框架,具体的细节,可以边百度边实现. test_three.py '''Test the Task data type.''' from collections ...
- asp.net 微信公众号源码
需要源码,请加QQ:858-048-581 功能菜单 该源码功能十分的全面,具体介绍如下:1.菜单回复:微信自定义回复.关注时回复.默认回复.文本回复.图文回复.语音回复. 请求回复记录.LBS位置回 ...
- 【POJ】1704.Georgia and Bob
题解 感觉挺神奇的 我们把石子从后往前相邻的两个两两配对,这样他们之间的空格就相当于一堆石子 而配对后左边棋子移动,右边棋子也一定可以跟上取 转化成简单的nim游戏,最后只要看转化出的这(N - 1) ...
- 启动win8.1时提示 api-ms-win-crt-runtime-l1-1-0.dll丢失
电脑里没有安装windows的更新KB2999226 到微软官网 https://www.microsoft.com/zh-cn/download/details.aspx?id=49081 下载对应 ...