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的更多相关文章

  1. [C# 基础知识梳理系列]专题六:泛型基础篇——为什么引入泛型

    引言: 前面专题主要介绍了C#1中的2个核心特性——委托和事件,然而在C# 2.0中又引入一个很重要的特性,它就是泛型,大家在平常的操作中肯定会经常碰到并使用它,如果你对于它的一些相关特性还不是很了解 ...

  2. C#基础知识梳理索引

    C#基础知识梳理索引 一 引子 之前曾写了一篇随笔<.NET平台技术体系梳理+初学者学习路径推荐+我们的愿景与目标> 三个月过去了,目标使更多的编程初学者,轻松高效地掌握C#开发的基础,重 ...

  3. Java自学-集合框架 泛型Generic

    ArrayList上使用泛型 步骤 1 : 泛型 Generic 不指定泛型的容器,可以存放任何类型的元素 指定了泛型的容器,只能存放指定类型的元素以及其子类 package property; pu ...

  4. [SQL] SQL 基础知识梳理(一)- 数据库与 SQL

    SQL 基础知识梳理(一)- 数据库与 SQL [博主]反骨仔 [原文地址]http://www.cnblogs.com/liqingwen/p/5902856.html 目录 What's 数据库 ...

  5. [SQL] SQL 基础知识梳理(二) - 查询基础

    SQL 基础知识梳理(二) - 查询基础 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5904824.html 序 这是<SQL 基础知识梳理( ...

  6. [SQL] SQL 基础知识梳理(三) - 聚合和排序

    SQL 基础知识梳理(三) - 聚合和排序 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5926689.html 序 这是<SQL 基础知识梳理 ...

  7. [SQL] SQL 基础知识梳理(四) - 数据更新

    SQL 基础知识梳理(四) - 数据更新 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5929786.html 序 这是<SQL 基础知识梳理( ...

  8. [SQL] SQL 基础知识梳理(五) - 复杂查询

    SQL 基础知识梳理(五) - 复杂查询 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5939796.html 序 这是<SQL 基础知识梳理( ...

  9. solr DIH 知识梳理

    solr DIH 知识梳理 web.xml中listener配置 <listener> <listener-class>org.apache.solr.handler.data ...

随机推荐

  1. Java单体应用 - 导读

    原文地址:http://www.work100.net/training/monolithic 更多教程:光束云 - 免费课程 Java单体应用 本阶段课程将学习如何进行Java单体Web应用开发,经 ...

  2. 使用Oracle Stream Analytics 21步搭建大数据实时流分析平台

    概要: Oracle Stream Analytics(OSA)是企业级大数据流实时分析计算平台.它可以通过使用复杂的关联模式,扩充和机器学习算法来自动处理和分析大规模实时信息.流式传输的大数据可以源 ...

  3. pycharm安装PIL失败

    搜索安装PIL后无法成功安装,在尝试各种版本后依旧无法解决 问题解决 安装Pillow-PIL,既可以成功执行代码 因为pil没有64位的版本,所以需要下载安装第三方支持64位系统的版本才可以使用.

  4. 字符串(String)的创建,以及字符串的属性及方法

    1.String对象的创建 方法1: var txt = new String("i am String"); console.log(txt); // 结果为:i am Stri ...

  5. String字符串性能优化的几种方案

    String字符串是系统里最常用的类型之一,在系统中占据了很大的内存,因此,高效地使用字符串,对系统的性能有较好的提升. 针对字符串的优化,我在工作与学习过程总结了以下三种方案作分享: 一.优化构建的 ...

  6. FTP服务后门利用

    开门见山 1. 扫描同网段的靶场机,发现PCS,192.168.31.137 2. 扫描靶场机服务信息和服务版本 3. 快速扫描靶场机全部信息 4. 发现开放ftp服务,并扫描此ftp软件版本是否存在 ...

  7. 请注意安全!你的mongodb已经被黑了!互联网安全生产大过天!

    你所不知道的入侵,你的服务器安全吗?你的数据库安全吗? 讲真,也许是我以前一直从事内网应用开发吧,我从来没有想过在互联网上,有那么多扫描器. 10月份的时候,受人委托我做了一个简单的抢单插件,里面有用 ...

  8. 面试总结 | Linux后台开发不得不看的知识点(给进军bat的你!)

    目录 一 自我介绍 二 面试情况 三 相关知识点汇总 1 c/c++相关 2 计算机网络 3 数据结构相关 4 数据库相关 5 操作系统 6 Linux基础知识及应用编程(后台必备!) 7 大数问题 ...

  9. java数据域初始化

    1.在声明中赋值 /** * Created by N3verL4nd on 2016/11/19. */ class Test{ private String str = "Hello W ...

  10. 说说GAN(生成式对抗网络)

    在Auto-encoder中,input data通过一个encoder神经网络得到一个维度的较低的向量,称这个向量为code,code经过一个decoder神经网络后输出一个output data. ...