概念
- 为什么需要泛型:编写程序的时候容易遇到两个模块功能相近但是参数类型不同,所以分别写多个方法处理每种数据类型,不能重用同样功能的代码。
- 用根类Object来解决存在的缺陷:
A:会出现装箱和拆箱的操作,将会在托管堆上分配和回收大量的变量,如果数量庞大,性能会损失严重。
B:虽然处理引用类型,没有装箱和拆箱的操作,但讲用到的数据类型强制转换的时候会增加处理器的负担 - 泛型:可以将类型作为参数来传递,创建类型的时候用一个特定的符号“T”来作为占位符。允许延迟编写类或者方法中数据类型的规范,也就是等到实例化时候再用一个实际的类型来替代。
- 好处:
A:解决了多个模块功能相近但是参数类型不同的问题。提高了重用性。
B:相对于用Object解决上述问题,泛型不用装箱拆箱,降低成本。
C: 可以堆泛型参数进行限定以访问特定数据类型,利用泛型约束。
使用
泛型方法
namespace Blog1
{
class Program
{
//泛型方法
public static void Swap<T>(ref T a,ref T b)
{
T temp = a;
a = b;
b = temp;
}
static void Main(string[] args)
{
double a = 10.0;
double b = 11.0;
Swap<double>(ref a, ref b);
Console.WriteLine("a:" + a + " b:" + b);
Console.ReadKey();
}
}
}
/*输出:
a:11 b:10
*/
泛型约束
- 泛型约束:对能都实例化类的类型种类施加限制。
- 好处:不让做一些约束类型不能做的,比如说约束了只能是值类型,方法里面却用约束的泛型做值类型不能做的,就会报错。
- 常用的约束类型:
约束 | 作用 |
---|---|
where T : struct | 泛型T是值类型(小数、整数、char、bool、struct) |
where T : class | 泛型T是引用类型 |
where T : new() | 泛型T具有一个无参数的构造方法,如果有多个约束,new()要放在最后。不能和struct一起用。 |
where T : 基类名 | 泛型T是该基类或者其派生类 |
where T : 接口名 | 泛型T是实现了该接口的类型 |
public void Test<T>(ref T a,ref T b)where T:struct
{}
- 约束多个泛型
public void Test<T,U>(ref T a,ref U b)where U:struct where T:class,new()
{}
泛型类
namespace Blog1
{
public class Car
{
public string name;
}
public class Maserati:Car
{
public Maserati()
{
name = "玛莎拉蒂";
}
}
//泛型类+约束
public class CarShop<T>where T : Car
{
List<T> List;
public CarShop()
{
List = new List<T>();
}
public void Buy(T car)
{
List.Add(car);
Console.WriteLine("进购"+car.name);
}
}
class Program
{
static void Main(string[] args)
{
CarShop<Car> shop = new CarShop<Car>();
shop.Buy(new Maserati());
Console.ReadKey();
}
}
}
/*输出:
进购玛莎拉蒂
*/
泛型接口
interface ITalk<T>
{
void Talk(T content);
}
public class Chinese<T> : ITalk<T>
{
public void Talk(T content)
{
Console.WriteLine("中国话:"+content);
}
}
泛型委托
- 自定义泛型委托
namespace Blog1
{
//泛型委托
public delegate void TestDelegate<T>(T test);
class Program
{
public static void Test1(int test)
{
Console.WriteLine("test1 num=" + test);
}
static void Main(string[] args)
{
TestDelegate<int> test = new TestDelegate<int>(Test1);
test(1);
Console.ReadKey();
}
}
}
/*输出:
test1 num=1
*/
- 内置的泛型委托:不用显示声明自定义的委托。
Func委托:内置的有返回值的泛型委托,可以接受0个至16个传入参数。
namespace Blog1
{
class Program
{
public static int Addtion(int x,int y)
{
return x + y;
}
static void Main(string[] args)
{
Func<int, int, int> addtion = Addtion;
int result = addtion(100, 2);
Console.WriteLine(result);
Console.ReadLine();
}
}
}
/*输出:
102
*/
Action委托:内置的无返回值的泛型委托,可以接受0个至16个传入参数。
namespace Blog1
{
class Program
{
public static void Addtion(int x,int y)
{
Console.WriteLine(x+y);
}
static void Main(string[] args)
{
Action<int, int> addtion = Addtion;
addtion(100, 2);
Console.ReadLine();
}
}
}
/*输出:
102
*/