.NET知识梳理——1.泛型Generic
1. 泛型Generic
1.1 引入泛型:延迟声明
泛型方法声明时,并未写死类型,在调用的时候再指定类型。
延迟声明:推迟一切可以推迟的。
1.2 如何声明和使用泛型
泛型方法:方法名称后面加上尖括号,里面是类型参数
类型参数实际上就是一个类型T声明,方法就可以用这个类型T了。
如下所示:
public static void Show<T>(T t)
{
Console.WriteLine($"This is {typeof(CustomMethod)},paramater={t.GetType().Name},value={t}");
}
1.3 泛型的好处和原理
泛型方法性能跟普通方法一致,泛型声明方法时,并未写死类型,T是什么类型,只有在调用的时候才知道,一个方法能满足不同类型。
1.4 泛型类、泛型方法、泛型接口、泛型委托
1.4.1 泛型类型
一个类满足不同类型的需求
具体如下:
public class BaseModel
{
public int Id { get; set; }
}
public class GenericClass<T>
where T:BaseModel//为泛型基类约束
{
}
1.4.2 泛型方法
一个方法满足不同类型的需求
具体如下:
public static void Show<T>(T t)
{
Console.WriteLine($"This is {typeof(CustomMethod)},paramater={t.GetType().Name},value={t}");
}
1.4.3 泛型接口
一个接口满足不同类型的需求
//泛型接口
public interface IGenericInterface<T>
{
public void SayHi(T t);
}
1.4.4 泛型委托
一个委托满足不同类型的需求
public delegate void Do<T>(T t);
1.5 泛型约束
没有约束,泛型会很局限。主要有5中泛型的约束。如下:
1.5.1 基类约束
Where T:BaseModel
可以把BaseModel当作基类
只有该类型的对象或从该类型派生出的对象,可被用作类型参数。(密封类约束的不行,因为没有意义。)
//基类
public class BaseModel
{
public int Id { get; set; }
}
//泛型类
public class GenericClass<T>
where T:BaseModel//为泛型基类约束
{
}
调用:
GenericConstraint.Show<BeiJing>(new BeiJing());
1.5.2 引用类型约束
//引用类型约束
public static T Get<T>() where T:class
{
return default(T);//default是关键字,根据类型T返回对应的默认值
}
调用:
GenericConstraint.Get<Person>(new Person());
1.5.3 值类型约束
//值类型约束
Public static D GetD<D>() where D:struct
{
return default(D);
}
调用:
GenericConstraint.GetD<int>(116);
1.5.4 无参数构造函数
//无参数构造函数约束
Public static S GetS<S>()
where S: new()//无餐构造函数约束
{
return new S();
}
调用:
GenericConstraint.GetS<Chinese>();
1.5.5 接口约束
//接口约束
public static void Show2<T>(T t) where T : ISports
{
t.Basketball();
}
调用:
GenericConstraint.Show2<USA>(new USA());
1.6 协变、逆变
所谓协变、逆变都是跟泛型有关的(多用在接口)。
1.6.1 协变
修饰返回值
让右边用子类,让泛型用起来更方便(子类转父类)
Out修饰,协变后只能是返回结果,不能做参数
IEnumerable<Bird> birdList=new List<Sparrow>();
//out 协变,只能是返回结果(子类转父类)
public interface ICustomerListOut<out T>
{
T Get();
}
public class CustomerListOut<T>:ICustomerListOut<T>
{
public T Get()
{
return default(T);
}
}
ICustomerListOut<Bird> list2 = new CustomerListOut<Sparrow>();
Func<Bird> func = new Func<Sparrow>(() => null);
IEnumerable<Bird> list3 = new List<Sparrow>();
1.6.2 逆变
修饰传入参数
让右边可以用父类,让泛型用起来更方便(父类转子类)
In修饰,逆变后只能当作参数
//in 逆变 只能是输入参数(父类转子类)
public interface ICustomerListIn<in T>
{
void Show(T t);
}
public class CustomerListIn<T>:ICustomerListIn<T>
{
public void Show(T t)
{
Console.WriteLine(t.GetType().Name);
}
}
//逆变
ICustomerListIn<Sparrow> list1 = new CustomerListIn<Bird>();
Action<Sparrow> action = new Action<Bird>((i) => { });
public interface IMyList<in inT,out outT>
{
void Show(inT t);
outT Get();
outT Do(inT t);
}
public class MyList<T, T1> : IMyList<T, T1>
{
public void Show(T t)
{
Console.WriteLine(t.GetType().Name);
}
public T1 Get()
{
Console.WriteLine(typeof(T1).Name);
return default(T1);
}
public T1 Do(T t)
{
Console.WriteLine(t.GetType().Name);
Console.WriteLine(typeof(T1).Name);
return default(T1);
}
}
IMyList<Sparrow, Bird> myList1 = new MyList<Sparrow, Bird>();
IMyList<Sparrow, Bird> myList2 = new MyList<Sparrow, Sparrow>();//协变
IMyList<Sparrow, Bird> myList3 = new MyList<Bird, Bird>();//逆变
IMyList<Sparrow, Bird> myList4 = new MyList<Bird, Sparrow>();//逆变+协变
1.7 泛型缓存
泛型缓存,每个类型都会生成一个不同的副本(适合不同类型需要缓存一份数据的场景)
public class GenericCache<T>
{
private static string _TypeTime = "";
static GenericCache()
{
Console.WriteLine("This is GenericCache 静态构造函数");
_TypeTime = $"{typeof(T).FullName}_{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}";
}
public static string GetCache()
{
return _TypeTime;
}
}
/// <summary>
/// 字典缓存:静态属性常驻内存
/// </summary>
public class DictionaryCache
{
private static Dictionary<Type, string> _TypeTimeDictionary = null;
static DictionaryCache()
{
Console.WriteLine("This is DictionaryCache 静态构造函数");
_TypeTimeDictionary = new Dictionary<Type, string>();
}
public static string GetCache<T>()
{
Type type = typeof(Type);
if (!_TypeTimeDictionary.ContainsKey(type))
_TypeTimeDictionary[type] = $"{typeof(T).FullName}_{DateTime.Now.ToString("yyyy-MM-dd HH mm:ss")}";
return _TypeTimeDictionary[type];
}
}
.NET知识梳理——1.泛型Generic的更多相关文章
- [C# 基础知识梳理系列]专题六:泛型基础篇——为什么引入泛型
引言: 前面专题主要介绍了C#1中的2个核心特性——委托和事件,然而在C# 2.0中又引入一个很重要的特性,它就是泛型,大家在平常的操作中肯定会经常碰到并使用它,如果你对于它的一些相关特性还不是很了解 ...
- C#基础知识梳理索引
C#基础知识梳理索引 一 引子 之前曾写了一篇随笔<.NET平台技术体系梳理+初学者学习路径推荐+我们的愿景与目标> 三个月过去了,目标使更多的编程初学者,轻松高效地掌握C#开发的基础,重 ...
- Java自学-集合框架 泛型Generic
ArrayList上使用泛型 步骤 1 : 泛型 Generic 不指定泛型的容器,可以存放任何类型的元素 指定了泛型的容器,只能存放指定类型的元素以及其子类 package property; pu ...
- [SQL] SQL 基础知识梳理(一)- 数据库与 SQL
SQL 基础知识梳理(一)- 数据库与 SQL [博主]反骨仔 [原文地址]http://www.cnblogs.com/liqingwen/p/5902856.html 目录 What's 数据库 ...
- [SQL] SQL 基础知识梳理(二) - 查询基础
SQL 基础知识梳理(二) - 查询基础 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5904824.html 序 这是<SQL 基础知识梳理( ...
- [SQL] SQL 基础知识梳理(三) - 聚合和排序
SQL 基础知识梳理(三) - 聚合和排序 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5926689.html 序 这是<SQL 基础知识梳理 ...
- [SQL] SQL 基础知识梳理(四) - 数据更新
SQL 基础知识梳理(四) - 数据更新 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5929786.html 序 这是<SQL 基础知识梳理( ...
- [SQL] SQL 基础知识梳理(五) - 复杂查询
SQL 基础知识梳理(五) - 复杂查询 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5939796.html 序 这是<SQL 基础知识梳理( ...
- solr DIH 知识梳理
solr DIH 知识梳理 web.xml中listener配置 <listener> <listener-class>org.apache.solr.handler.data ...
随机推荐
- set(待整理)
set集合容器:实现了红黑树的平衡二叉检索树的数据结构,插入元素时,它会自动调整二叉树的排列,把元素放到适当的位置,以保证每个子树根节点键值大于左子树所有节点的键值,小于右子树所有节点的键值:另外,还 ...
- ASENET MVC 5 with Bootstrap and Knockout.js 第一弹
A Basic Example Now that the Knockout library is installed, let’s get right to an example of using ...
- BZOJ4559 成绩比较
题目传送门 分析: 我们可以先试着求一下,对于单个学科,有多少种分配方案可以使B神排名为R 对于第i个学科 \(~~~~g(i)=\sum_{j=1}^{H_i}j^{n-R_i}(H_i-j)^{R ...
- 51Nod 2026 Gcd and Lcm
题目传送门 分析: 开始玩一个小小的trick 我们发现\(f(n)=\sum_{d|n}\mu(d)\cdot d\)是一个积性函数 所以: \(~~~~f(n)=\prod f(p_i^{a_i} ...
- 树莓派通过模数转换芯片ADC0832读取LM35温度传感器数据
树莓派通过模数转换芯片ADC0832读取LM35温度传感器数据 今天和小朋友一起玩树莓派,打算来做一个测量室温的小实验.经过几个小时的研究和测试,终于能够成功读取LM35传感器的温度数据了.本文主要记 ...
- Python3之json文件操作
json函数 使用json函数之前,首先需要导入json模块,import json 1).json.dumps()函数 该函数是将 Python 对象编码成 JSON 字符串,例如: import ...
- vue3的打包及打包的坑
1.vue3没有vue.config.js文件,在根目录下建一个vue.config.js文件 2.vue.config.js 3.vue3.3版本前的打包命令 vue3.3版本之后 我用3.3之 ...
- Future、Callback、Promise
推荐下边两篇,写的很棒 https://juejin.im/post/5b126065e51d4506bd72b7cc https://www.cnkirito.moe/future-and-prom ...
- Azure 认知服务概述
背景知识 近些年随着机器学习.深度学习等技术的不断发展,人工智能在越来越多的场景得到了应用,如人脸识别.图像识别.语音识别.语音生成.自然语言处理.决策分析等等,让机器拥有了听.说.看和思考的能力,很 ...
- jdk8 ConcurrentHashMap分析
ConcurrentHashMap分析 tryPresize() transfer() putVal() addCount() sumCount() class ConcurrentHashMap { ...