本篇文章主要介绍泛型的应用。

泛型是.NET Framework 2.0 版类库就已经提供的语法,主要用于提高代码的可重用性、类型安全性和效率。

泛型的定义

下面定义了一个普通类和一个泛型类,我们可以明确看到泛型类和普通类最大的区别就是多了一个<T>。

所以,这个<T>就标记了,这个类是泛型类。其中这个T,也可以写成A,B,C,D或其他字符。

public class Generic
{
public String Name;
}
public class Generic<T>
{
public T Name;
}

泛型,顾名思义,就是泛指的类型。好比男人,女人,白人,黑人,可以泛称为【人】。

但类型只能是一个类型。 那么泛型和类型之间是什么关系呢?

其实很简单,泛型在定义的时候,是泛指类型;在使用的时候,就需要被指定,到底使用哪个类型。

即,使用时,就不在是泛指类型,而是特定类型。

好比,定义时,定义了一个人。但在使用时,必须明确指定,到底是黑人还是白人。

泛型的使用

泛型类跟普通类的使用方式一样,都需要实例化对象,再由对象来调用内部的属性或方法。

下面代码实例化了泛型Generic,实例化时,还指定了该泛型Generic的指定类型为String。

所以要给泛型Generic的属性Name赋值,就需要赋值字符串类型的值。

public static void Excute()
{
Generic<String> gs = new Generic<String>();
gs.Name = "Kiba518";
}

下面代码定义了一个Int类型的泛型Generic。

public static void Excute()
{
Generic<int> gs = new Generic<int>();
gs.Name = 518;
}

泛型的默认值

泛型的默认值,如下面代码所示。需要使用default(T)来赋值。

不管泛型到底是String,int,bool或者是一个Class类型,都可以被自动赋值。

public static void Excute()
{
Generic<int> gs = new Generic<int>();
gs.Name = 518;
Generic<Task> gsTask = new Generic<Task>();
gsTask.Name = new Task(()=> {
Console.WriteLine("Kiba518");
});
} public class Generic<T>
{
public T Name = default(T);
}

泛型的约束

在泛型类中,有个特别的约束可供我们使用。

当我们不显示的声明时,这个约束不存在。但当我们显示的声明的时候,这个约束就会执行。

下面,我们来看看这个特别的约束。

public static void Excute()
{
Generic<FanXing> gFanXing = new Generic<FanXing>();
Generic<Base> gFanXingBase = new Generic<Base>();
//Generic<string> gs = new Generic<string>(); 这样定义会报错
}
public class Generic<T> where T : Base
{
public T Name = default(T);
}
public class Base
{
public string Name { get; set; }
}
public class FanXing : Base
{
public new string Name { get; set; }
}

如上面代码所示,【where T : Base】就是这个特别的约束。

当显示声明这个约束的时候,定义会限制泛型的类型。

什么是限制泛型的类型呢?

很简单,泛型T,是泛指某一个类型。我们在定义泛型类时,还需显示的指定类型,此时我们显示指定的类型,要受这个限制。

这个限制就是指【where T : Base】。

它的限制是,要求我们指定的类型T必须是Base,或者该类型继承自Base,如FanXing类。

泛型的函数

在C#中,泛型不仅可以用于类,还可以直接用于函数。

具体使用方式如下:

 public static void Excute()
{
GenericFunc gf = new GenericFunc();
gf.FanXingFunc<FanXing>(new FanXing() { Name="Kiba518"});
}
public class GenericFunc
{
public void FanXingFunc<T>(T obj)
{
Console.WriteLine(obj.GetType());
}
}

很简单,调用泛型函数的时候,指定泛型函数的[指定类型]即可。

但是,这里我们发现一个问题,那就是,在泛型函数里,使用泛型对象的时候,我们发现对象都是object类型的。

那我们如果想使用泛型对象里的属性和方法时,要怎么办呢?

也很简单,反射就可以了。

下面我们添加一个反射函数GetPropertyValue,专门用来获取属性。

public class GenericFunc
{
public void FanXingFunc<T>(T obj)
{
var name = GetPropertyValue(obj, "Name");
Console.WriteLine(name);
}
public object GetPropertyValue(object obj, string name)
{
object drv1 = obj.GetType().GetProperty(name).GetValue(obj, null);
return drv1;
}
}

输出结果如下:

这样我们就得到了我们想要的结果,如果想使用泛型类里的函数,道理也一样,只需要用反射来调用即可。

结语

看到这里,有些同学可能会觉得泛型很复杂,连使用其对象下的属性,都得反射,太繁琐了,还不如不用呢。

有这样想法的同学,心里想想就好了,如果对老司机这么说,他肯定会内心默默的微笑,然后对你说,你想的没错。

然后,你就没有然后了。

泛型的应用,开篇已经说了,主要用在提高代码的可重用性、类型安全性和效率上。

如果只是定义一个类,调用一个属性,那泛型的存在就是鸡肋。

但事实上,我们的系统永远只有更复杂,更复杂,更复杂。因此泛型才有了用武之地。

C#语法——委托,架构的血液

C#语法——元组类型

C#语法——await与async的正确打开方式

----------------------------------------------------------------------------------------------------

注:此文章为原创,任何形式的转载都请联系作者获得授权并注明出处!
若您觉得这篇文章还不错,请点击下方的【推荐】,非常感谢!

C#语法——泛型的多种应用的更多相关文章

  1. C#面试题(转载) SQL Server 数据库基础笔记分享(下) SQL Server 数据库基础笔记分享(上) Asp.Net MVC4中的全局过滤器 C#语法——泛型的多种应用

    C#面试题(转载) 原文地址:100道C#面试题(.net开发人员必备)  https://blog.csdn.net/u013519551/article/details/51220841 1. . ...

  2. C#语法——泛型的多种应用 C#语法——await与async的正确打开方式 C#线程安全使用(五) C#语法——元组类型 好好耕耘 redis和memcached的区别

    C#语法——泛型的多种应用   本篇文章主要介绍泛型的应用. 泛型是.NET Framework 2.0 版类库就已经提供的语法,主要用于提高代码的可重用性.类型安全性和效率. 泛型的定义 下面定义了 ...

  3. 从一知半解到揭晓Java高级语法—泛型

    目录 前言 探讨 泛型解决了什么问题? 扩展 引入泛型 什么是泛型? 泛型类 泛型接口 泛型方法 类型擦除 擦除的问题 边界 通配符 上界通配符 下界通配符 通配符和向上转型 泛型约束 实践总结 泛型 ...

  4. C#核心语法-泛型(详细讲解泛型方法、泛型类、泛型接口、泛型约束,了解协变逆变)

    泛型(generic)是C#语言2.0和通用语言运行时(CLR)的一个新特性.泛型为.NET框架引入了类型参数(type parameters)的概念.类型参数使得设计类和方法时,不必确定一个或多个具 ...

  5. Java学习笔记-基础语法Ⅷ-泛型、Map

    泛型 泛型本质上是参数化类型,也就是说所操作的数据类型被指定为一个参数,即将类型由原来的具体的类型参数化,然后在使用/调用时传入具体的类型,这种参数类型可以用在类.方法和接口中,分别为泛型类.泛型方法 ...

  6. C#语法——反射,架构师的入门基础。

    前言 编程其实就是写代码,而写代码目的就是实现业务,所以,语法和框架也是为了实现业务而存在的.因此,不管多么高大上的目标,实质上都是业务. 所以,我认为不要把写代码上升到科学的高度.上升到艺术就可以了 ...

  7. C#语法——消息,MVVM的核心技术。

    在C#中消息有两个指向,一个指向Message,一个指向INotify.这里主要讲INotify. INotify也有人称之为[通知],不管叫消息还是通知,都是一个意思,就是传递信息. 消息的定义 I ...

  8. C#语法——事件,逐渐边缘化的大哥。

    事件是C#的基础之一,学好事件对于了解.NET框架大有好处. 事件最常见的比喻就是订阅,即,如果你订阅了我的博客,那么,当我发布新博客的时候,你就会得到通知. 而这个过程就是事件,或者说是事件运行的轨 ...

  9. C#语法——委托,架构的血液

    本篇文章主要介绍委托的应用. 委托是大家最常见的语法了,但会用与精通之间的差别是巨大的. 一个程序员如果不能精通委托,那么,他永远无法成为高级程序员. 所以,让我们把委托刻到血液里吧. 这样,你才能称 ...

随机推荐

  1. bzoj 1076 奖励关 状压+期望dp

    因为每次选择都是有后效性的,直接dp肯定不行,所以需要逆推. f[i][j]表示从第i次开始,初始状态为j的期望收益 #include<cstdio> #include<cstrin ...

  2. P2P综述

    原文参见:http://www.lotushy.com/?p=113 [TOC] 什么是P2P P2P全称是Peer-to-peer.P2P计算或P2P网络是一种分布式应用架构.它将任务或负载分发给P ...

  3. CentOS7解决firefox无法启用ibus中文输入的问题

    最近换电脑,要换掉使用了6年的旧环境,开始折腾重装系统: 下了minimal版本的CentOS7.4,然后开始一点点装想用的东西,多少找到一点十年前折腾LFS的感觉:然后竟然被输入法拌住了半天,事后回 ...

  4. 什么是语义化的HTML?为什么要做到语义化?

    一.什么是语义化的HTML? 语义化的HTML就是写出的HTML代码,符合内容的结构化(内容语义化),选择合适的标签(代码语义化),能够便于开发者阅读和写出更优雅的代码的同时让浏览器的爬虫和机器很好地 ...

  5. 事务处理中如何获取同一个connection 对象

    运用线程内部的map属性,将对象绑定到ThreadLocal中: 具体实现: 1.新建一个绑定Connection对象的单例类 public class ConnectionBind { privat ...

  6. J2EE相关概念,EJB/JNDI/JMS/RMI等

    J2EE 四层模型 J2EE的核心API.组件.相关概念 JDBC(Java Database Connectivity) JNDI(Java Name and Directory Interface ...

  7. Django_cookie_session

    登录时候后台打印request.COOKIE 1.login页面正确登录的话,后台页面可以获取到浏览器携带的cookie的. 2.第一行的sessionid其实就是cookie值 3.session的 ...

  8. 使用BeetleX的TcpBenchmark工具进行百万设备模拟测试

    其实TCP测试的工具有很多,那BeetleX工具所提供的特点又是什么呢?如果你需数十万的请求或模拟上百万的设备连接,那这个工具相信可以满足你的需要!工具是基于BeetleX的基础功能扩展,支持多IP绑 ...

  9. 我手写的简易tomcat

    前述 自己手写的简易的tomcat,实现了tomcat的基本响应功能,项目代码已经上传到我的Github,刚刚开始学习这里,当前还存在很多问题 项目简述及代码 当我们的Web运行的时候,从浏览器发出的 ...

  10. 阿里微服务架构下分布式事务解决方案-GTS

    虽然微服务现在如火如荼,但对其实践其实仍处于初级阶段.即使互联网巨头的实践也大多是试验层面,鲜有核心业务系统微服务化的案例.GTS是目前业界第一款,也是唯一的一款通用的解决微服务分布式事务问题的中间件 ...