前言:

    此系列都为个人对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. 什么是JS事件冒泡?

    什么是JS事件冒泡?: 在一个对象上触发某类事件(比如单击onclick事件),如果此对象定义了此事件的处理程序,那么此事件就会调用这个处理程序,如果没有定义此事件处理 程序或者事件返回true,那么 ...

  2. nginx 虚拟主机基于端口的搭建

    首先配置nginx.conf [root@localhost conf]# cat nginx.confworker_processes 1;user nginx nginx;error_log /a ...

  3. ios10.2真机调试包,ios升级10.2后需要添加

    下载地址: http://download.csdn.net/detail/koktear/9710820 添加地址: finder-应用程序-找到Xcode-右击显示包内容-Contents-Dev ...

  4. 树莓派3B更新软件

    因为软件是要不断更新的,所以半个月或者一个月要升级一下软件 升级软件非常简单 在终端或者SSH里输入 sudo apt-get update && apt-get upgrade -y ...

  5. 4-安装workpress

    安装wordpress 软件下载 https://cn.wordpress.org/releases/ 在mysql数据库中创建wordpress数据库 mysql> create databa ...

  6. java.util.ConcurrentModificationException 解决办法(转载)

    今天在项目的中有一个需求,需要在一个Set类型的集合中删除满足条件的对象,这时想当然地想到直接调用Set的remove(Object o)方法将指定的对象删除即可,测试代码:   public cla ...

  7. Boolean()值为false的五个特殊值

    在if.while等需要判断条件时,会调用函数Boolean()对判断条件进行隐式转换,而只有五个特殊值才会返回false 这五个值是:undefined, null, "", 0 ...

  8. [LeetCode] Maximum Product of Word Lengths 单词长度的最大积

    Given a string array words, find the maximum value of length(word[i]) * length(word[j]) where the tw ...

  9. 给空签名包进行签名以及找不到keystore证书链问题的解决方案

    转 http://blog.csdn.net/u011106842/article/details/49683865

  10. [转]ExtJs基础--Html DOM、Ext Element及Component三者之间的区别

    要学习及应用好Ext框架,必须需要理解Html DOM.Ext Element及Component三者之间的区别. 每一个HTML页面都有一个层次分明的DOM树模型,浏览器中的所有内容都有相应的DOM ...