前言:

    此系列都为个人对C#的回顾,属于个人理解,新司机可参考、求老司机指点。如果有什么问题或不同见解,欢迎大家与我沟通!   


目录: 

   泛型是什么

泛型的好处及用途

如何声明使用泛型

泛型类

泛型方法

泛型接口

泛型委托

泛型约束

  • 泛型是什么

    通过“参数化类型(不指定类型)”来实现在同一份代码上操作多种数据类型。

     在声明时不指定类型,编译后查看IL代码可看到生成为占位符“`1”(1表示只有一个泛型参数,两个就是`2,以此类推)   ,调用时会生成不同类型的方法,也就是最终还是会生成多个方法!

    

  • 泛型的好处及用途

     我们来假设一个场景:需要在控制台输出各种类型(可能不太形象,个人感觉ORM框架中数据保存那块很形象)。

     在泛型没出现之前,我们基本都是采用以下这种方式来实现:

    

     这个时候该有人说了这样写以后扩展太麻烦,咱可以采用object,毕竟object是所有类型的基类,也就是以下这种:

    

     确实,类型不明确的地方可以使用object类型,一样可以达到目的。不过这种办法会引起:

     1.使用object导致的类型安全问题

     2.拆箱装箱导致性能下降

     泛型的出现就是为了解决以上几种情况的问题,上面那个例子可以改为:

    

     综其上述,泛型的好处有:

     1.泛型采用延迟声明思想,将“参数化类型”将类型抽象化,从而实现更为灵活的复用。

     2.泛型赋予了代码更强的类型安全,更高的效率,更清晰的约束。

     泛型的用途很广泛,在.net各处都有体现,比如常见的List<T>、IEnumerable<T>、ICollection<T>等等。个人觉得说起泛型就应该说说委托。。。

     例如:Linq中的方法都是采用的泛型加委托

     

  • 如何声明使用泛型

    泛型类:

     /// <summary>
/// 这就是一个泛型类,是不是很简单
/// </summary>
/// <typeparam name="T">类型参数</typeparam>
public class Generic<T>
{
/// <summary>
/// 泛型方法
/// </summary>
/// <param name="type">泛型参数,根据类指定</param>
/// <returns></returns>
public T OutPut(T type)
{
Console.WriteLine(type.GetType());
return default(T);
}
} public class Test
{
Generic<int> genericInt;
Generic<string> genericString;
public Test()
{
//泛型类调用1
genericInt = new Generic<int>();
genericInt.OutPut();
//泛型类调用2
genericString = new Generic<string>();
genericString.OutPut("我就是泛型方法,不过我的参数类型是根据类来决定的,我的兄弟会在下面粗现~~");
}
}

    泛型方法:

     public class Generic<T>
{
/// <summary>
/// 泛型方法
/// </summary>
/// <param name="type">泛型参数,根据类指定</param>
/// <returns></returns>
public T OutPut(T type)
{
Console.WriteLine(type.GetType());
return default(T);//default(T)返回类型默认值
} /// <summary>
/// 泛型方法,注意看,我与上面不同哦!调用也不同哦!
/// </summary>
/// <typeparam name="TResult"></typeparam>
/// <param name="tresult"></param>
/// <returns></returns>
public TResult GenericAction<TResult>(TResult tresult)
{
Console.WriteLine(tresult.GetType());
return default(TResult);
}
/// <summary>
/// 可以随便写,类上面也一样~~~~~
/// </summary>
public TResult GenericAction<TResult, LResult, SResult>(TResult tresult,LResult lresult,SResult sresult)
{
Console.WriteLine(tresult.GetType());
return default(TResult);
}
} public class Test
{
Generic<int> genericInt;
Generic<string> genericString;
Generic<DateTime> genericDateTime;
public Test()
{
//泛型类调用1
genericInt = new Generic<int>();
genericInt.OutPut();
//泛型类调用2
genericString = new Generic<string>();
genericString.OutPut("我就是泛型方法,不过我的参数类型是根据类来决定的,我的兄弟会在下面粗现~~");
//泛型方法调用3
genericDateTime = new Generic<DateTime>();
genericDateTime.GenericAction<string>("我的最终输出结果是根据方法的类型参数决定的,跟类无关!");
}
}
}

    泛型接口:

     //泛型接口
public interface IGeneric<T>
{
}
//普通类继承泛型接口,需要指定基类泛型类型
public class Generic : IGeneric<string>
{
}
//泛型类继承泛型接口
public class Test<T> : IGeneric<int>
{
}
//泛型类继承泛型接口,并运用子类的泛型类型
public class Test1<T> : IGeneric<T>
{
}
//随便怎么玩都可以~~~~~~~其他的大家都可以试试

    泛型委托:个人觉得泛型委托是个重点,在.net中处处体现了这点,比如我上面所说到的Linq方法。如果有对委托不熟悉的,我会在后面写一篇关于对委托的介绍。

       1.首先我们先自定义一个泛型委托

     class Program
{
//这里定义了一个无参有返回值的泛型的委托
public delegate T CustomDelegate<T>();
//这里定义了一个有参有返回值的泛型的委托
public delegate T CustomDelegate1<T>(T type); static void Main(string[] args)
{
//声明这个无参有返回值泛型委托
CustomDelegate<int> customDelegate = new CustomDelegate<int>(() => { return ; });//() => { return 1; }匿名方法
//调用这个泛型委托
customDelegate.Invoke(); //声明这个有参有返回值泛型委托
CustomDelegate1<string> customDelegate1 = new CustomDelegate1<string>((i) => { return i; });
customDelegate1.Invoke("有参有返回值"); //其他的无参无返回值,有参无返回值大家都可以试下,也可以尝试定义成多个参数的委托试试!!!
}
}

    2.微软在.net为我们封装好的三个泛型委托,为了简化咱们的工作量,不用自定义委托

 class Program
{
static void Main(string[] args)
{
//1.Func
Func<string> func = new Func<string>(() => { return default(string); }); //2.Action
Action<string> action = new Action<string>((i) => { }); //3.Predicate
Predicate<bool> pre = new Predicate<bool>((i) => { return true; }); //这三个泛型委托用处不同.
//比如Func就在Linq方法中经常用到,在F12进去之后可以看到类型参数上带有out修饰符
//Action,在F12进去之后可以看到类型参数上带有in修饰符
//in 与 out 则就是我们后面要说的逆变与协变了
//Predicate,则就是一个条件判断委托了
//具体的应用场景大家可以想象下
}
}

    泛型约束:

      在定义泛型类时,可以对客户端代码能够在实例化类时用于类型参数的类型种类施加限制。如果客户端代码尝试使用某个约束所不允许的类型来实例化类,则会产生编译时错误。这些限制称为约束。约束是使用 where 上下文关键字指定的。下表列出了六种类型的约束:

约束 说明

T:结构

类型参数必须是值类型。可以指定除 Nullable 以外的任何值类型。有关更多信息,请参见使用可空类型(C# 编程指南)。

T:类

类型参数必须是引用类型,包括任何类、接口、委托或数组类型。

T:new()

类型参数必须具有无参数的公共构造函数。当与其他约束一起使用时,new() 约束必须最后指定。

T:<基类名>

类型参数必须是指定的基类或派生自指定的基类。

T:<接口名称>

类型参数必须是指定的接口或实现指定的接口。可以指定多个接口约束。约束接口也可以是泛型的。

T:U

为 T 提供的类型参数必须是为 U 提供的参数或派生自为 U 提供的参数。这称为裸类型约束。

    1.T:结构

    2.T:类

    3.T:new()

 

    4.T:<基类名>

    5.T:<接口名称>

    6.T:U


扩展:

  让我们通过泛型与泛型委托来扩展一个IEnumerable方法(需要了解C#扩展方法)

     public static class Extends  //静态类
{
/// <summary>
/// 只要有一个满足于predicate条件就返回true
/// </summary>
/// <typeparam name="TSource"></typeparam>
/// <param name="tsource"></param>
/// <param name="predicate"></param>
/// <returns></returns>
public static bool MaxBool<TSource>(this IEnumerable<TSource> tsource, Func<TSource, bool> predicate)
{
foreach (var item in tsource)
{
if (predicate(item))
{
return true;
}
}
return false;
}
} static void Main(string[] args)
{
//为什么List能使用MaxBool()我就不用说了吧。。。。。
List<int> listA = new List<int>() { , , };
bool trueOrFalse = listA.MaxBool(item => item > );
}

   这里只是一个简单的例子,大家可以试试对其他的进行扩展!

 

C#:泛型(Generic)的更多相关文章

  1. Java - 泛型 ( Generic )

    Java - 泛型 ( Generic )     > 泛型的特点         > 解决元素存储的安全性问题         > 解决获取数据元素时,需要类型强转的问题     ...

  2. Java之集合初探(二)Iterator(迭代器),collections,打包/解包(装箱拆箱),泛型(Generic),comparable接口

    Iterator(迭代器) 所有实现了Collection接口的容器都有一个iterator方法, 用来返回一个实现了Iterator接口的对象 Iterator对象称作迭代器, 用来方便的实现对容器 ...

  3. 谈一谈从 Delphi 2009 之后就支援的重要功能 – 泛型 (Generic)

    前言 在C++的语言基础当中,除了物件导向.事件驱动的概念之外,模版设计(Template)也是非常重要的一环.然而,C++的开发人员能够善用模版设计的并不多.模版设计这个好物,一般还有一个名称,就是 ...

  4. JAVA中的泛型(Generic)

    Java泛型(Generic)简介 泛型是jdk1.5版本以后推出来的,表示类型参数化,让java能更具有动态性一些,让类型能变成参数传递. 要我自己感觉的话,泛型本身没啥用,跟反射在一起用,就体现出 ...

  5. Dephi泛型generic的应用

    Dephi泛型generic的应用   泛型在C++, C#中已有广泛应用,Delphi自2009版本也引入泛型,典型的应用如TList,TDictionary.如果你熟悉C#,其用法十分类似. 比如 ...

  6. Java基础之Comparable接口, Collections类,Iterator接口,泛型(Generic)

    一.Comparable接口, Collections类 List的常用算法: sort(List); 排序,如果需要对自定义的类进行排序, 那就必须要让其实现Comparable接口, 实现比较两个 ...

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

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

  8. C#泛型(Generic)

    一.什么是泛型 泛型(Generic)是C#语言2.0.通用语言运行时(CLR)2.0..NET Framework2.0推出来的新特性. 泛型为.NET框架引入类型参数(Type Parameter ...

  9. .NET知识梳理——1.泛型Generic

    1. 泛型Generic 1.1        引入泛型:延迟声明 泛型方法声明时,并未写死类型,在调用的时候再指定类型. 延迟声明:推迟一切可以推迟的. 1.2        如何声明和使用泛型 泛 ...

  10. C# 泛型Generic

    泛型(Generic),是将不确定的类型预先定义下来的一种C#高级语法,我们在使用一个类,接口或者方法前,不知道用户将来传什么类型,或者我们写的类,接口或方法相同的代码可以服务不同的类型,就可以定义为 ...

随机推荐

  1. ASP.NET MVC Routing、Areas、URLs

    webForm页面运行起来url一般是这样的:localhost:****/index.aspx,这个过程就是当你运行页面的时候,vs开发工具自带的微型服务器会打开你存在硬盘上的这个文件然后显示在浏览 ...

  2. Linux下MySQL慢查询分析mysqlsla安装使用

    说明: 操作系统:CentOS 5.X 64位 MySQL版本:mysql-5.5.35 MySQL配置文件:/etc/my.cnf MySQL 数据库存放目录:/data/mysql 实现目的:开启 ...

  3. python写红包的原理流程包含random,lambda其中的使用和见简单介绍

    Python写红包的原理流程 首先来说说要用到的知识点,第一个要说的是扩展包random,random模块一般用来生成一个随机数 今天要用到ramdom中unifrom的方法用于生成一个指定范围的随机 ...

  4. spi子系统之驱动SSD1306 OLED

    spi子系统之驱动SSD1306 OLED 接触Linux之前,曾以为读源码可以更快的学习软件,于是前几个博客都是一边读源码一边添加注释,甚至精读到每一行代码,实际上效果并不理想,看过之后就忘记了.主 ...

  5. 理解Docker(8):Docker 存储之卷(Volume)

    (1)Docker 安装及基本用法 (2)Docker 镜像 (3)Docker 容器的隔离性 - 使用 Linux namespace 隔离容器的运行环境 (4)Docker 容器的隔离性 - 使用 ...

  6. HDOJ 2317. Nasty Hacks 模拟水题

    Nasty Hacks Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Tota ...

  7. android文件的写入与读取---简单的文本读写context.openFileInput() context.openFileOutput()

      最终效果图,点击save会保存到文件中,点击show会从文件中读取出内容并显示. main.xml <?xml version="1.0" encoding=" ...

  8. codevs 2597 团伙

    时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题目描述 Description 1920年的芝加哥,出现了一群强盗.如果两个强盗遇上了,那么他们要么是朋友,要么 ...

  9. [LeetCode] Surrounded Regions 包围区域

    Given a 2D board containing 'X' and 'O', capture all regions surrounded by 'X'. A region is captured ...

  10. 关于AngularJS(1)

      在讲正题之前,先说一下有关angular简介方面的信息: 1. angularJS  诞生于2009年,由Misko Hevery 等人创建,后为Google所收购.是一款优秀的前端JS框架,已经 ...