一、自定义泛型方法(Generic Method),将类型参数用作参数列表或返回值的类型:

void MyFunc<T>() //声明具有一个类型参数的泛型方法
{
Type genericType = typeof(T); //在泛型方法体内部获取类型参数的类型信息
//do…
}
//调用泛型方法
MyFunc<int>();

  1.声明泛型方法时,可以在参数列表中使用这个类型参数:void MyFunc<T>(T obj) { };此时在调用该泛型方法时可以省略类型参数的指定由编译器推断其类型,例如:MyFunc<int>(myNum)与MyFunc(myNum)完全等效;

  2.声明泛型方法时,可以在返回值类型中使用这个类型参数:T MyFunc<T>() { return default(T); };编译器的类型推断功能不适用于仅在返回值类型中使用类型参数的情况,此种情况在调用时必须显式指定类型参数;

  3.声明泛型方法时,方法的参数列表和返回值可以指定相同或不相同的类型参数,如果不相同则一般参数列表的类型参数在前,返回值的类型参数在后:U MyFunc<T, U>(T obj) { return default(U); },此时依然不能使用编译器的类型推断功能;如果相同,则在调用时可以使用编译器的类型推断功能省略类型参数的显式指定;
类型参数数量的不同,可以构成重载方法:

void MyFunc() { }
void MyFunc<T>() { }
void MyFunc<T, U>() { }

  4.泛型方法中的类型参数也可以指定约束;

  5.在泛型类中声明的方法,方法的参数列表和返回值可以使用泛型类的类型参数作为类型;泛型方法可出现在泛型或具体类型中,只有当方法有属于自己的类型参数时才是泛型方法,在泛型类中声明泛型方法时,二者类型参数的占位符不可以相同:

class MyClass<T> //声明一个泛型类,类型参数占位符为T
{
void MyFunc(T obj) //声明一个非泛型方法,使用泛型类的类型参数T作为参数类型
{
//do…
}
//不能声明泛型方法void MyFunc<T>,泛型方法的类型参数占位符不能与类的类型参数占位符相同
void MyFunc<U>(T obj1, U obj2) //声明一个泛型方法,类型参数占位符为U
{
//do…
}
}
class MyClass //定义一个具体类
{
void MyFunc<T>(T obj) //声明一个泛型方法
{
//do…
}
}

  二、自定义泛型接口(Generic Interface),将类型参数用作参数列表或返回值的类型:

interface IMyInterface<T> //定义具有一个类型参数的泛型接口
{
void MyFunc(T obj); //声明参数为T的方法
}
//声明泛型类继承自泛型接口
public class MyClass<T> : IMyInterface<T>
{
public void MyFunc(T obj)
{
//do…
}
}
//指定类型参数为string类型,创角泛型类的实例赋值给泛型接口的变量
IMyInterface<string> iMyInterface = new MyClass<string>();

  1.适用于泛型类的规则基本也适用于泛型接口;

  三、自定义泛型委托(Generic Delegate),将类型参数用作参数列表或返回值的类型:

delegate void MyDelegate<T>(T obj); //定义具有一个类型参数的泛型委托,参数列表中有一个参数
void MyGenericFunc<T>(T obj) //声明一个泛型方法,参数列表中有一个参数
{
//do…
}
void MyFunc(string str)
{
//do…
}
//声明泛型委托的实例,指定类型参数为string类型,此时可匹配的方法签名为void myFunc(string str)
MyDelegate<string> myDelegate;
//赋值一个指定类型参数为string的泛型方法
myDelegate = MyGenericFunc<string>;
//添加一个参数列表为string类型的具体方法
myDelegate += MyFunc;

  1.泛型委托同泛型类一样,需要在实例化时指定类型参数的类型;

  2.泛型委托的实例同具体委托的实例一样,只需要方法的参数列表和返回值类型相同即可进行匹配,因此不管目标方法是指定了符合要求类型的泛型方法还是具体方法都可以进行匹配; 

  四、反射中的泛型:

Type myType = typeof(MyClass<>); //获取未指定任何类型参数的开放式构造类的类型信息,多个类型参数时添加,:typeof(MyClass<,>)
myType = myType.MakeGenericType(typeof(int)); //通过类型信息的实例方法MakeGenericType()构建指定所有类型参数的封闭式构造类的类型信息,如未指定所有类型参数会抛出异常ArgumentException
//也可以直接获取封闭式构造类的类型信息,当类型参数在一开始就确定时推荐使用此种方式
//myType = typeof(MyClass<int>); //多个类型参数时需要同时指定:typeof(MyClass<int, string>)

  1.通过反射只可以获取未指定任何类型参数的开放式构造类的类型信息和指定所有类型参数的封闭式构造类的类型信息,即无法获取MyClass<int, >的类型信息;


如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的认可是我写作的最大动力!

作者:Minotauros
出处:https://www.cnblogs.com/minotauros/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

详解C#泛型(二)的更多相关文章

  1. 详解C#泛型(二) 获取C#中方法的执行时间及其代码注入 详解C#泛型(一) 详解C#委托和事件(二) 详解C#特性和反射(四) 记一次.net core调用SOAP接口遇到的问题 C# WebRequest.Create 锚点“#”字符问题 根据内容来产生一个二维码

    详解C#泛型(二)   一.自定义泛型方法(Generic Method),将类型参数用作参数列表或返回值的类型: void MyFunc<T>() //声明具有一个类型参数的泛型方法 { ...

  2. 详解C#泛型(三)

    一.前面两篇文章分别介绍了定义泛型类型.泛型委托.泛型接口以及声明泛型方法: 详解C#泛型(一) 详解C#泛型(二) 首先回顾下如何构建泛型类: public class MyClass<T&g ...

  3. JavaScript学习笔记-实例详解-类(二)

    实例详解-类(二)   //===给Object.prototype添加只读\不可枚举\不可配置的属性objectId(function(){ Object.defineProperty(Object ...

  4. Android开发:文本控件详解——TextView(二)文字跑马灯效果实现

    一.需要使用的属性: 1.android:ellipsize 作用:若文字过长,控制该控件如何显示. 对于同样的文字“Android开发:文本控件详解——TextView(二)文字跑马灯效果实现”,不 ...

  5. 【Java入门提高篇】Day30 Java容器类详解(十二)TreeMap详解

    今天来看看Map家族的另一名大将——TreeMap.前面已经介绍过Map家族的两名大将,分别是HashMap,LinkedHashMap.HashMap可以高效查找和存储元素,LinkedHashMa ...

  6. CocoaPods详解之(二)----进阶篇

    CocoaPods详解之----进阶篇 作者:wangzz 原文地址:http://blog.csdn.net/wzzvictory/article/details/19178709 转载请注明出处 ...

  7. Java源码详解系列(十二)--Eureka的使用和源码

    eureka 是由 Netflix 团队开发的针对中间层服务的负载均衡器,在微服务项目中被广泛使用.相比 SLB.ALB 等负载均衡器,eureka 的服务注册是无状态的,扩展起来非常方便. 在这个系 ...

  8. [转]iOS学习之UINavigationController详解与使用(二)页面切换和segmentedController

    转载地址:http://blog.csdn.net/totogo2010/article/details/7682433 iOS学习之UINavigationController详解与使用(一)添加U ...

  9. dom对象详解--document对象(二)

       dom对象详解--style对象 style对象 style对象和document对象下的集合对象styleSheets有关系,styleSheets是文档中所有style对象的集合,这里讲解的 ...

  10. MySQL存储过程详解 mysql 存储过程(二)

    mysql存储过程详解 1.      存储过程简介 我们常用的操作数据库语言SQL语句在执行的时候需要要先编译,然后执行,而存储过程(Stored Procedure)是一组为了完成特定功能的SQL ...

随机推荐

  1. 2.2.2synchronized同步代码块的使用

    当两个并发线程访问同一个对象object中的synchronized(this)同步代码块时,一段时间内只能有一个线程执行,另一个线程必须等待期执行完才能执行. package com.cky.bea ...

  2. Mysql之数据库操作

    数据库操作: 链接数据库: mysql -uroot -p masql -uroot -pmysql 退出数据库: exit/quit/ctrl + d   sql语句最后需要分号结尾: 查看时间: ...

  3. Qt_HelloWrold

    新建工程 -> 选择Qt Gui 应用 然后点击选择 在弹出的对话框中填写名称,创建路径等信息: 点击下一步,选择该工程的编译器. 点击下一步,可以选择生成的主窗口文件.不过这里我们仅仅用简单的 ...

  4. UIImageView的frame设置(4种方式)

    查看图片宽高后,再去设置UIImageView的frame.(不推荐) 用代码自动获取图片的宽高来设置UIImageView的frame: 创建UIImageView的同时,直接设置UIImageVi ...

  5. std::set 中内部元素有序条件删除的理解

    std::set 中内部元素有序条件删除的理解 1. std::set中的元素是有序排列的 注意:Set集合中的元素通过iterator的引用,但是不能修改. 元素排序: (1)元素中实现比较oper ...

  6. ajax点击加载更多图片

    <!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>& ...

  7. UniGUI的 TUniPageControl控件动态拖动tabsheet的实现方法

    https://blog.csdn.net/shuiying/article/details/54932518 实现可以用鼠标动态拖动tabsheet,共三个步骤: 1.在ServerModule中, ...

  8. jwt身份认证

    项目地址:https://github.com/cuongle/WebApi.Jwt

  9. C#Datetimepicker出现问题及解决方法

    前几天公司用的物料管理系统出现了一个很奇怪的问题,具体的现象是:10月31号的那天,物流部的人因为之前的问题,需要将之前已经结转的9月份取消结转. ,当操作人员将10改变为9的时候,出现问题了.程序直 ...

  10. MariaDB 用户与权限管理(12)

    MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可MariaDB的目的是完全兼容MySQL,包括API和命令行,MySQL由于现在闭源了,而能轻松成为MySQ ...