C#语法之泛型
前面两篇C#语法主要是回顾委托相关的。这篇主要回顾了泛型。
一、为什么要有泛型?
我们在写一些方法时可能会方法名相同,参数类型不同的方法,这种叫做重载。如果只是因为参数类型不同里面做的业务逻辑都是相同的,那可能就是复制粘贴方法,改变参数类型,例如一些排序算法,int、float、double等类型的排序,参数数组存的数据类型不一样,还有像根据索引找到List集合中的对象。可能这个对象是Person、Dog等对象,这样方法改变的只是参数类型,那就是能不能写一个方法,传递不同的参数类型呢?于是乎有了泛型。
二、什么是泛型?
泛型通过参数化类型来实现在同一份代码上操作多种数据类型。例如使用泛型的类型参数T,定义一个类Stack<T>,可以用Stack<int>、Stack<string>或Stack<Person>实例化它,从而使类Stack可以处理int、string、Person类型数据。这样可以避免运行时类型转换或封箱操作的代价和风险,类似C++的模板。泛型提醒的是将具体的东西模糊化,这与后面的反射正好相反。
三、泛型demo
1.泛型类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Generic
{
public class Stack<T>
{
private T[] s; int pos; public Stack(int size)
{
s = new T[size];
pos = ;
} public void Push(T val)
{
s[pos] = val;
pos++;
} public T Pop()
{
pos--;
return s[pos];
} public void display()
{
Console.WriteLine("Stack Push:");
foreach (T i in s)
{
Console.WriteLine(i);
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Generic
{
class Program
{
static void Main(string[] args)
{
Stack<int> s1 = new Stack<int>();
s1.Push();
s1.Push();
s1.display(); Console.WriteLine("Stack Pop:");
Console.WriteLine(s1.Pop());
Console.WriteLine(s1.Pop()); Stack<string> s2 = new Stack<string>();
s2.Push(@"One");
s2.Push(@"Two");
s2.display(); Console.WriteLine("Stack Pop:");
Console.WriteLine(s2.Pop());
Console.WriteLine(s2.Pop()); Console.ReadLine(); }
}
}
上面定义了一个泛型类,主要是维护一个栈,栈里存放T类型的数据,在demo中可以定义int、string类型的栈,这样就很方便,使用一套代码可以维护多种数据类型。如果没有这个可能还要维护double、float等代码。
2.泛型方法
上面是泛型类,主要是在类层面进行参数化,我们还可以在更小的层面,在函数上进行泛型化。
我们可以在上面Mina类中定义一个静态的泛型方法,用来获取找数值在数组中的位置。
public static int Find<T>(T[] valus, T val)
{
for (int i = ; i < valus.Length; i++)
{
if (valus[i].Equals(val))
{
return i;
}
}
return -;
}
我们可以用上面的方法来查找int数组、float数组
int val = ;
int pos = Find<int>(new int[] {,,,, },val);
Console.WriteLine(string.Format("int Pos:{0}",pos)); float val1 = ;
pos = Find<float>(new float[] { , , , , }, val1);
Console.WriteLine(string.Format("float Pos:{0}", pos));
Console.ReadLine();
下面是两个demo的输出

四、约束
约束是指对泛型类型参数施加限制,用于限制可以传递到该类型参数的类型种类。如果使用某个约束不允许的类型来实例化,则会产生编译时错误。约束使用where关键字指定。
约束有4种类型:
1.基类约束
指定编译器泛型类型参数必须派生自特定基类
修饰符 class 类名<类型参数列表> where 类型参数:基类名
{ 类体}
2.接口约束
指定编译器泛型类型参数必须派生自特定接口
修饰符 class 类名<类型参数列表> where 类型参数:接口名
{ 类体}
3.默认构造函数约束
指示编译器泛型类型参数公开了默认的公共构造函数(不带任何参数的公共构造函数)
修饰符 class 类名<类型参数列表> where 类型参数:new ()
{ 类体}
4.引用/值类型约束
指示编译器泛型类型参数必须是引用类型或值类型
修饰符 class 类名<类型参数列表> where 类型参数:struct(或class)
{ 类体}
可以对同一类型参数使用多个约束,并且约束自身可以也可以是泛型类型,多个约束之间用逗号隔开。
五、泛型委托
泛型委托主要是想讲一下Action<T>和Func<TResult>两个委托,因为这两个在Linq中是经常见到的。
Action<T>只能委托必须是无返回值的方法
Fun<TResult>只是委托必须有返回值的方法
不管是不是泛型委托,只要是委托委托那能用Lamdba表达式,因为不管Lamdba表达式还是匿名函数其实都是将函数变量化。
下面简单的来做的demo说下两个的用法,这个会了基本linq会了一半了。
Action<string> action = s => {
Console.WriteLine(s);
};
action("cuiyanwei");
Func<int, int, int> func = (int a, int b)=>{
return a + b;
};
int result=func(, );
Console.WriteLine("sum:{0}",result);
Console.ReadLine();
上面其实都是将函数做为变量,这也是委托的思想。action是实例化了一个只有一个字符串参数没有返回值得函数变量。func是实例化了一个有两个int类型的参数返回值为int的函数变量。下面来看下输出结果:

我们可以看到通过Lamdba表达式和泛型的结合,算是又方便了开发者们,更加方便实用。
最后在这传统佳节情人节,祝各位单身狗(包括我)早日脱单,不过说实话今天我还是挺高兴的,朋友玩失踪又出现了,这算是节日最大的快乐吧。
C#语法之泛型的更多相关文章
- Java17-java语法基础——泛型
Java18-java语法基础——泛型 一.泛型概念和作用 1.泛型概念: 泛型是JavaSE1.5的新特性,泛型的本质是参数化类型,也就是说,所操作的数据类型被指定为一个参数.这种参数类型可以用在类 ...
- C#基础语法之-泛型
泛型:一共7个知识点 1.引入泛型,延迟声明 2.如何声明和使用泛型 3.泛型的好处和原理 4.泛型类,泛型方法,泛型接口,泛型委托 5.泛型约束 6.协变,逆变 7.泛型缓存 一.为啥会出现泛型,有 ...
- Swift2.1 语法指南——泛型
原档:https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programmi ...
- delphi新语法之泛型实现的对象池模板
现在的DELPHI因为支持泛型的语法,所以也能支持模板编程了. // 标准模板 unit UntPools; interface uses Classes, SysUtils, Unt ...
- C#核心语法讲解-泛型(详细讲解泛型方法、泛型类、泛型接口、泛型约束,了解协变逆变)
泛型(generic)是C#语言2.0和通用语言运行时(CLR)的一个新特性.泛型为.NET框架引入了类型参数(type parameters)的概念.类型参数使得设计类和方法时,不必确定一个或多个具 ...
- C#高级语法之泛型、泛型约束,类型安全、逆变和协变(思想原理)
一.为什么使用泛型? 泛型其实就是一个不确定的类型,可以用在类和方法上,泛型在声明期间没有明确的定义类型,编译完成之后会生成一个占位符,只有在调用者调用时,传入指定的类型,才会用确切的类型将占位符替换 ...
- 泛型(8)-Java7的"菱形"语法与泛型构造器
正如泛型方法允许在方法签名中声明泛型形参一样,Java也允许在构造器签名中声明泛型形参,这样就产生了所谓的泛型构造器. package com.j1803;class Foo{ public < ...
- C# 语法特性 - 泛型(C#2.0)
泛型将 类型参数 的概念引入了 .NET Framework. 泛型主要有两个优点: 1.编译时可以保证类型安全. 2.不用做类型转换,获得一定的性能提升. 泛型方法.泛型委托.泛型接口 除了泛型类之 ...
- C#语法糖之第五篇: 泛型委托- Action<T>
因为工作的原因(其实还是个人的惰性)昨天没有给大家分享文章,然后这几天也有很多园友也提出了他们报告的意见及指导,再次感谢这些兄弟们的照顾我 和支持,这个分类的文章我当时想的是把我的学习经验和工作中用到 ...
随机推荐
- python 几种方法实现随机生成8位同时包含数字、大写字符、小写字符密码的小程序
python 实现随机生成包8位包含大写字母.小写字母和数字的密码的程序.要求:1用户输入多少次就生成多少条密码,2要求密码必须同时包含大写字母.小写字母和数字,长度8位,不能重复代码如下: impo ...
- ASP.NET Core 2 学习笔记(五)静态文件
之前的ASP.NET网站,只要把*.html.*.css.*.jpg.*.png.*.js等静态文件放在项目根目录,默认都可以直接被浏览:但ASP.NET Core 小改了浏览静态文件的方式,默认根目 ...
- c# 调用短信平台接口,给手机发送短信
项目上要做个发手机短信的功能.网上找找了,用的微米的短信接口. 注册后,获得UID和UID key,C#代码中需要这个 调用代码很简单 ", con = "[微米]您的验证码是:6 ...
- Mac OS 10.12 - Gogland和在Windows中使用的不同!!
刚刚在Mac OS 10.12用Gogland写了一个小小的GO语言测试程序,经过一番尝试才算把Gogland配置好,写出这个测试程序!Gogland在Mac OS 10.12里和Windows里面确 ...
- 双向链表的实现——c++
c++实现双向链表 : #ifndef DOUBLE_LINK_HXX #define DOUBLE_LINK_HXX #include <iostream> using namespac ...
- 匹配img标签的正则表达式
$preg = '/<img.*?src=[\"|\']?(.*?)[\"|\']?\s.*?>/i';//匹配img标签的正则表达式 preg_match_all($ ...
- Linux的软硬链接
Linux链接分为两种,一种是硬链接一种是符号链接. 硬链接: 硬链接是指通过索引节点来进行.再Linux文件系统中,保存在磁盘分区中的文件不管是什么类型都给它分配一个编号,称为索引节点(Inode ...
- Hadoop2.2.0安装笔记
最近想学习hadoop,于是网上找了些教程学习,几经周折,总算安装成功了! 先讲下环境,就2台机器...都是vmware虚拟机,操作系统centos, jdk版本 1.8.0 hadoop版本 2.2 ...
- 2019年北航OO第一次博客总结
一.基于度量对程序结构的分析 1. 第一次作业 1.1 基于类的分析的度量 首先,基于类的属性个数,方法个数,每个方法的规模,每个方法的控制分支数目,类总代码规模等特征对本次作业的结构进行分析. 1. ...
- ConcurrentHashMap的使用注意事项
有人说:虽然ConcurrentHashMap是线程安全的,但是在如下的代码中: ConcurrentHashMap<String,String> map; String getStrin ...