泛型:拥有让多种类型共享一组代码的能力。
- 在声明语句中,在方法名、类名、接口名、结构名、委托类型名后,使用一个"<占位符1,占位符2>"(如:List
、Action<T1,T2>)来替代真实的数据类型这就完成了泛型的创建 - 这些占位符被称为类型参数、使用了类型参数后方法变成了泛型方法、类变成了泛型类、接口变成了泛型接口...
- 泛型类、泛型方法等不能直接使用,只有用真实的数据类型代替类型参数:如 List
、Action<string,int>...才可以使用--而这一过程被称为特化
static void ShowInfo(int param)
{
Console.WriteLine($"{param.GetType().FullName}--{param}");
}
static void ShowInfo(string param)
{
Console.WriteLine($"{param.GetType().FullName}--{param}");
}
static void ShowInfo(double param)
{
Console.WriteLine($"{param.GetType().FullName}--{param}");
}
通过观察,便可看出:上面的方法除了操作的数据类型不同外,在功能上是相同的;可以将代码改写成下面形式:
通过将方法声明为泛型方法,无论是预定义类型、用户自定义类型等,都可以共享同一组代码了。
static void ShowInfo<T>(T param)
{
Console.WriteLine($"{param.GetType().FullName}--{param}");
}
泛型类
声明泛型类
- 在类名后面放一对尖括号
- 在尖括号中可以放置一个或多个占位符来表示希望提供的类型,这些占位符也成为类型参数
- 在类体中,可以使用类型参数替代实际类型
class MyStack<T>
{
private int startPointer = 0;
private T[] stackArray;
public void Push(T item)
{
//压栈
}
public T Pop()
{
//弹栈
return stackArray[stackArray.Length-1];
}
}
使用泛型类
- 为泛型参数提供实际的数据类型替补空缺--否则我们无法使用泛型类
- 声明特化了的泛型实例
- 使用实例调用方法
static void Main(string[] args)
{
//使用int来替代T
MyStack<int> myStack;
//像普通类型创建实例那样,创建Mystack<int>类型实例
myStack = new MyStack<int>();
//调用方法
myStack.Push(11);
int popItem = myStack.Pop();
Console.ReadLine();
}
泛型能够提高性能
class Program
{
static void Main(string[] args)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
Console.WriteLine($"开始:{stopwatch.ElapsedMilliseconds}");
for (int i = 0; i < 1000; i++)
{
ShowInfo(i);
}
Console.WriteLine(stopwatch.ElapsedMilliseconds);
stopwatch.Restart();
Console.WriteLine($"重新开始:{stopwatch.ElapsedMilliseconds}");
for (int i = 0; i < 1000; i++)
{
ShowInfo<int>(i);
}
Console.WriteLine(stopwatch.ElapsedMilliseconds);
Console.ReadLine();
}
static void ShowInfo<T>(T param)
{
Console.WriteLine($"{param.GetType().FullName}--{param}");
}
static void ShowInfo(int param)
{
Console.WriteLine($"{param.GetType().FullName}--{param}");
}
}
运行结果:
类型参数的约束:包括where子句和约束类型
//使用where子句,使类型参数T继承ICompare接口,这样parma1便可以使用CompareTo方法了
static bool IsLessThan<T>(T param1, T param2) where T : IComparable
{
return param1.CompareTo(param2) < 0 ? true : false;
}
where子句
- 如果需要对于单个类型参数,提供多个约束,则使用","隔开
static bool IsLessThan<T1,T2>(T1 param1, T2 param2) where T1 : struct,IComparable
{
return param1.CompareTo(param2) < 0 ? true : false;
}
- 如果需要对多个类型参数提供约束,则使用多个where子句--注意:where之间不需要使用","
static bool IsLessThan<T1, T2>(T1 param1, T2 param2) where T1 : struct, IComparable
where T2 : class
{
return param1.CompareTo(param2) < 0 ? true : false;
}
约束类型:按照出现顺序约束一共下面几种
- 主约束(只能有一个):
- 类名---表明类型参数属于该类型或者继承了该类型
- class---表明类型参数是一种引用类型
- struct---表明类型参数是一种值类型
- 次要约束(可以多个):
- 接口名---此约束表明类型参数是实现了该接口的类型
- 构造函数约束:多个约束时放在最后面
- new()---此约束表明类型参数是一种带有公共无参构造函数的类型
下面展示一下约束类型的使用(仅为展示用,实际中可能并不会这样写)
static bool IsLessThan<T1, T2>(T1 param1, T2 param2) where T1 : Student, IComparable
where T2 : class,new()
{
return param1.CompareTo(param2) < 0 ? true : false;
}
以上便是对泛型的概念的总结,关于泛型还有很多未总结的知识点,放在后面再写。