泛型
泛型类
允许您延迟编写类或方法中的编程元素的数据类型的规范,直到实际在程序中使用它的时候。
泛型相当于类型占位符
定义
//定义格式:访问修饰符 class 类名<T> //T为替代的类型参数,可以用任意字母数字组合, // { // public T value; // }
//定义格式:访问修饰符 class 类名<T> // { // public T value; // } public class Test<T> { public T value; public void Call() { Console.WriteLine(value.GetType()); } } public class Test1<T1,T2> //通常使用T,多个泛型时,使用逗号分隔<T0,T1,T2> { public T1 value1; public T2 value2; }
使用
泛型类在使用时,需要指定类型,类中使用代替符号
定义的变量都为该指定类型
static void Main(string[] args) { Test<int> t1 = new Test<int>(); Test<string> t = new Test<string>(); t.value = "10"; t.Call(); Test1<string, int> t2 = new Test1<string, int>(); }
泛型方法
T类型可以用在形参的类型,也可以用在返回值类型,也可以在方法内使用
定义
//无参无返回值 static void Fun1<T>() { Console.WriteLine("我是无参无返回值"); } //无参有返回值 static T Fun2<T>() { return default(T); } //有参无返回值 static void Fun3<T>(T t1) { if(t1 is int ) { Console.WriteLine("T1是int"); } } //有参有返回值 static T0 Fun4<T0, T1>(T0 t0, T1 t1) { return t0; }
使用
泛型方法在使用时,需要指定类型,方法中使用代替符号定义的变量或返回值,则都为该指定类型。
可以通过default类获取该类型的默认值
static void Main(string[] args) { Fun1<string>(); int f = Fun2<int>(); Console.WriteLine("无参有返回值:{0}",f); //Fun3<int>(1); //如果有参数 <>内可以省略 Fun3(1); //string f4 = Fun4<string, int>("", 2); //如果有参数 <>内可以省略 string f4 = Fun4("abc", 2); Console.WriteLine("Fun4结果:{0}",f4); }
效果:
泛型约束
//where T:struct 指定类型,必须是值类型 //where T:class 指定类型,必须是引用类型 //where T:new() 指定类型,必须有无参数的公共构造函数 //where T:类名 指定类型,必须是该类名或该类的派生类 //where T:接口名 指定类型,必须是该接口或继承该接口的类型 //where T:U 指定类型,该类型必须是U类型或U类型的派生类型 //where T:class, new() 对同一个泛型进行多个约束,中间用“,”隔开 //where T0:struct where T1:class 对多个泛型进行分别约束,两个where间用空格隔开
class Program { static void Main(string[] args) { Test<int> t1 = new Test<int>(); //Test<string> t2 = new Test<string>(); Test1<string> t2 = new Test1<string>(); //Test2<Test3> t3 = new Test2<Test3>(); Test4<Test3> t4 = new Test4<Test3>(); Test4<Tool> t5 = new Test4<Tool>(); Test5<IFly> t6 = new Test5<IFly>(); Test5<Tool> t7 = new Test5<Tool>(); Test6<Test3> t8 = new Test6<Test3>(); t8.Function<Tool>(); } } public class Test<T> where T:struct { } public class Test1<T> where T : class//引用类型 { } public class Test2<T> where T : new()//必须有无参数的公共构造函数 { } public class Test3 { //private Test3() //{ //} } public class Tool:Test3,IFly { public void Fly() { } } public class Test4<T> where T:Test3 { } public interface IFly { void Fly(); } public class Test5<T> where T :IFly { } public class Test6<U> { public void Function<T>() where T:U { } } public class Test7<T> where T:class,new() { } //public class Test8<T> where T:struct,new() //{ //} /// <summary> /// 对每一个泛型进行单独约束 /// </summary> /// <typeparam name="T0"></typeparam> /// <typeparam name="T1"></typeparam> public class Test8<T0,T1> where T0:struct where T1:class { }
补充练习
public class Person { public string name; } public class Player : Person { } interface IFly { void Fly(); } class Pig:IFly { public void Fly() { Console.WriteLine("猪真的飞了"); } } class Program { static void Main(string[] args) { Test<Student> t1 = new Test<Student>(); //struct结构体是数值型,符合约束类型 //Test<string> t2 = new Test<string>(); //数组、字符串等是引用类型 ,所以无法创建对象 Test2<int[]> t3 = new Test2<int[]>(); //class约束只能用引用类型 t3.value = new int[3]; //实例化一个int类型数组 t3.value[0] = 1; Console.WriteLine(t3.value[0]); Test3<Student> t4 = new Test3<Student>(); t4.value.name = "吕布"; Console.WriteLine("t4:{0}",t4.value.name); //Test4<int> t5 = new Test4<int>(); //因为指定类名Person只能用Person或者其派生类Player类型 Test4<Player> t6 = new Test4<Player>(); t6.value = new Player(); //需要先实例化指定类名的类 t6.value.name = "指定类名"; Console.WriteLine(t6.value.name); Test5<Pig> t7 = new Test5<Pig>(); t7.value = new Pig(); //指定类型为class类名的都要实例化 t7.value.Fly(); Test6<Pig> t8 = new Test6<Pig>(); t8.value = new Pig(); t8.Can<Pig>(); //没搞明白。。。 Test7<Player> t9 = new Test7<Player>(); t9.value = new Player(); t9.value.name = "多种约束"; Console.WriteLine(t9.value.name); Test8<Student, Player> t10 = new Test8<Student, Player>(); t10.value.name = "泛型1"; t10.value2 = new Player(); t10.value2.name = "泛型2"; Console.WriteLine("value:{0},value2:{1}",t10.value.name,t10.value2.name); } } class Test<T> where T:struct { //必须是值类型 public T value; } struct Student:IFly { public string name; public int age; public void Fly() { Console.WriteLine("学生也会飞"); } } class Test2<T> where T:class { //必须是引用类型 public T value; } class Test3<T> where T:new() //指定类型,必须有无参的公开构造函数 结构体和类都可以 { public T value; } class Test4<T> where T: Person { public T value; } class Test5<T> where T:IFly { public T value; } class Test6<U> //U可以换成任意字母 约束该类 { public U value; public void Can<T>() where T:U //对方法约束,指定类型和该类指定的类型一样 { Console.WriteLine("跟类指定的类型相同的方法"); } } class Test7<T> where T:Person, new() //对一个泛型进行多种约束 “,”分割 { public T value; } class Test8<T1,T2> where T1:struct where T2:new() //对多种泛型分别约束 空格隔开 { public T1 value; public T2 value2; }
泛型接口
泛型实例:单例
static void Main(string[] args) { Student s = Student.Instance; Student s2 = Student.Instance; s.name = "s的名字"; Console.WriteLine(s2.name); Person p1 = Person.Instance; Person p2 = Person.Instance; p1.name = "饿汉模式"; Console.WriteLine(p2.name); } } //懒汉模式 用的时候才会new一个实例 public class Singleton<T> where T : class, new() { private static T _instance; public static T Instance { get { if (_instance == null) { _instance = new T(); } return _instance; } } } //饿汉模式 直接new出一个实例 public class EagerSingleton<T> where T: class,new() //new()要放在最后 { private static T _instance = new T(); //定义变量时直接实例一个对象 public static T Instance { get { return _instance; } } } class Student : Singleton<Student> //继承懒汉模式 类型放入自己的类型 { public string name; } class Person:EagerSingleton<Person> //继承饿汉模式 类型放入自己的类型 { public string name; }
数据结构
概念
数据结构是带有结构特性的数据元素的集合
结构特性
线性表
数组、链表
散列表
哈希表、字典。。。
栈(先入后出)
队列(先入先出)
树:二叉树
图
动态数组
练习1
练习2