C# Generics 泛型
C# Generics 泛型
泛型优点
性能
为了让方法传递任何类型的参数,可以用object类来传递参数。值类型转换为引用类型称为装箱,引用类型转换为值类型称为拆箱,需要强制转换。如下代码所示:
数据规模较大时装箱和拆箱操作性能损失较大。
// ArrayList 存储对象var list = new ArrayList();list.Add(0); // 装箱操作 把值类型转换为引用类型int item = (int)list[0]; // 拆箱操作 把引用类型转换为值类型
泛型在使用时定义类型,例如List<T>。下列代码List<T>的泛型类型定义为int,减少了装箱和拆箱的操作,提高了性能。
var g_list = new List<int>();g_list.Add(0);int g_item = g_list[0];
类型安全
主要是为了提早发现错误。例如使用ArrayList和List<T>。
// 使用ArrayList,当循环至list[1]时无法把string类型转换为int型var list = new ArrayList();list.Add(0);list.Add("item");foreach(int i in list){}
// List<T>泛型类型定义为int,在添加string类型时就报错var g_list = new List<int>();g_list.Add(0);g_list.Add("item");// 此时就会报错
代码重用
泛型类可以只定义一次,就可以用许多不同的类型实例化。例如List<T>只定义一次就可以实例化int类型、string类型等:
var ilist = new List<int>();var slist = new List<string>();
泛型类
创建一个双向链表,定义为泛型类。首先需要定义双向链表的结点:
// 双向链表的结点类 Value 可以存储任何类型的值public class LinkedListNode<T>{private T Value { get; set; }public LinkedListNode<T> Next { get; set; }public LinkedListNode<T> Prev { get; set; }public LinkedListNode(T value){Value = value;}}
类中定义了往链表中尾结点增加结点的方法。
public class LinkedList<T>{ public LinkedListNode<T> First { get; set; } // 头结点public LinkedListNode<T> Last { get; set; } // 尾结点public LinkedListNode<T> AddLast(T value){var newnode = new LinkedListNode<T>(value);if(First == null){ First = newnode;Last = First;}else{LinkedListNode<T> pre = Last;Last.Next = newnode;Last = newnode;Last.Prev = pre;}return newnode;}}
泛型类的功能:
- 默认值
T d = default(T) ,泛型中,default将泛型类型初始化为null或者0; - 约束
泛型类需要调用泛型类型中的方法,就必须添加约束。
where T : struct 结构约束,类型T必须是值类型
where T : class 类约束,类型T必须是引用类型
where T : IFoo 指定类型T必须实现接口IFoo
where T :Foo 指定类型T必须派生自基类Foo
where T :new() 构造函数约束,指定类型T必须有一个默认的构造函数
where T1 : T2 类型T1派生自泛型类型T2,T2也可以指定类型 - 继承
泛型类可以实现泛型接口,也可以派生自泛型基类。
要求必须重复接口的泛型类型:public class Drived<T>:Base<T>{}
或者必须指定基类的类型:public class Drived<T>:Base<string>{} - 静态成员
泛型类的静态成员只能在类的一个实例中共享,以下使用两个类型,因此会存在两组静态字段。
public class StaticDemo<T>{ public static int x;}
StaticDemo<string>.x = 4;
StaticDemo<int>.x = 5;
泛型接口
定义泛型接口
public interface IComparable<T>
{int CompareTo(T other);
}
泛型接口的协变和抗变
泛型接口定义用in或out关键词标注时,out表示协变,in表示抗变。
public interface ITest<out T>{}也就意味接口中的方法定义返回类型只能是T;同理public interface ITest<in T>{}表示泛型类型T只能用作方法的输入。
看代码更好理解:
// T1用in标识表示只能用于定义参数类型,T2用out标识标志表示只能用于定义返回值类型public interface InterfaceOutOrIn<in T1,out T2>{T2 GetT2();void SetT1(T1 t);T2 GetT2ByT1(T1 t);}
泛型结构
泛型结构和泛型类类似,泛型结构没有继承特性。
public struct Test<T>{private T Value;public Test(T value){Value = value;}public T getvalue(){return Value;}}
static void Main(string[] args){var t_int = new Test<int>(10);var t_string = new Test<string>("this is a string");Console.WriteLine($"t_int={t_int.getvalue()},t_string={t_string.getvalue()}");Console.ReadLine();}
泛型方法
在泛型方法中,泛型类型用方法声明来定义。
public class TestStudent{public void GetParam<T>(T tParam){Student std = tParam as Student;Console.WriteLine($"类型为{tParam.GetType()},FirstName={std.FirstName},LastName={std.LastName}");}}public class Student{private string firstName;private string lastName;public string FirstName { get; set; }public string LastName { get; set; }}
static void Main(string[] args){TestStudent cls = new TestStudent();var std = new Student{ FirstName = "Simon",LastName="Y"};cls.GetParam(std);Console.ReadLine();}
此时,如果定义一个Teacher类:
public class Teacher{private string name;private int age;public string Name { get; set; }public int Age { get; set; }}
并且新建Teacher类的一个实例teacher,调用GetParam方法,编译通过,运行时报错。
static void Main(string[] args){TestStudent cls = new TestStudent();var std = new Student{ FirstName = "Simon",LastName="Y"};var teacher = new Teacher { Name = "K", Age = 30 };cls.GetParam(std);cls.GetParam(teacher);Console.ReadLine();}
由于GetParam方法的参数只能输入Student类型,所以可以添加约束:
public void GetParam<T>(T tParam) where T:Student{Student std = tParam as Student;Console.WriteLine($"类型为{tParam.GetType()},FirstName={std.FirstName},LastName={std.LastName}");}
此时编译失败,因为teacher是自定义Teacher类型而非Student类型:
C# Generics 泛型相关推荐
- Dart基础之Generics 泛型 <T>
Java开发过程中,会通过重载实现根据不同的参数类型生成类似方法(多态),进一步可以通过 泛型 进一步提取基类方法:而对于 Dart 而言,为了解决多种方式构造对象的场景,也可以通过 Dart 中的 ...
- JavaSE-Adventure(III): Generics 泛型程序设计
JavaSE-Adventure (III): 泛型程序设计 CONTENTS JavaSE-Adventure (III): 泛型程序设计 概述 泛型概念 泛型的提出背景 泛型的作用 使用泛型 泛型 ...
- typescript学习:Generics泛型
本文内容如下 泛型Generics的了解与使用 如果你都有了答案,可以忽略本文章,或去TS学习地图寻找更多答案 泛型 定义:占位符,定义时不知道未来需要什么值,等调用的时候再传 作用:提升类,接口,方 ...
- 第四章 Generics - 泛型
现在,你已经知道了Swift中如何实现基本的类和结构,但Swift的强大远不止如此.本章要讲的是Swift的另一个非常强大的语法:泛型. 对于类型安全的语言来说,都有一个常见的问题.想写一个作用于一种 ...
- Generics (泛型)
Generics 是 JDK 5.0 新增加的功能,在使用集合时,提供了一种编译时类型安全检查功能,并能减少类型强制转化的麻烦. 当从一个集合中取出一个元素时,例如使用 Iterator 接口中的 n ...
- TypeScript Generics(泛型)
软件工程的一个主要部分就是构建组件,构建的组件不仅需要具有明确的定义和统一的接口,同时也需要组件可复用.支持现有的数据类型和将来添加的数据类型的组件为大型软件系统的开发过程提供很好的灵活性. 在C#和 ...
- Java基础学习——泛型(generics)学习一
概述 在JDK 5.0,Java语言引入了好几个新的功能,其中很重要的一个就是泛型(generics). 本文就是对泛型的一个概述.你可以很熟悉其他语言中的类似结构,比如C++里的模板(templat ...
- 9.1-全栈Java笔记: 容器泛型—认识Collection接口
开发和学习中需要时刻和数据打交道,如果组织这些数据是我们编程中重要的内容. 我们一般通过"容器"来容纳和管理数据. 事实上,数组就是一种容器,可以在其中放置对象或基本类型数据. ...
- java 泛型嵌套泛型_Java泛型嵌套
package com.study.generics; //泛型的嵌套使用 public class GenericsDemo06 { public static void main(String [ ...
最新文章
- 语音社交产品,安全合规“防坑指南”!
- 编译器C-Free V352注册算法分析
- mybatis There is no getter for property named '*' in 'class java.lang.String
- c语言 stm32结构体赋值,STM32学习笔记9——结构体赋值问题
- hp服务器系统检测,HP服务器检测步骤.pdf
- Packet Tracer 思科模拟器入门教程 实验报告1
- 网站编辑,你们的名字叫搬运工?
- 对话李国权:新加坡为什么能成为全球Web3.0创业的节点?
- 盘点人工智能高薪职位
- 支付宝InfoStr怎么获取
- Linux下pppd拨号脚本配置
- 电商场景化营销主要从哪几方面展开行无疆带你了解
- 英爱特快速制表软件详细介绍
- vmware虚拟机中的Linux桥接模式上网
- [ROC-RK3568-PC] [Firefly-Android] 10min带你了解GPIO复用
- python文字编辑器推荐_推荐5个常用的文本编辑器
- 大数据 人工智能 数据库 数据仓库
- HR人力资源系统管理源码
- 站长问答:百度突然不收录了怎么办?
- 【JAVASE】Java泛型实例化