generic

Generic   泛型

.Net Framework 1.0 2.0 时期没有泛型 ,当时为了满足一个方法满足不同类型的需求, 聪明的前辈们使用 Object类型作为方法的参数,会有装箱 拆箱导致的效率问题 , 以及类型安全问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
namespace Generic {
public class CommonMethod {
public static void ShowObject(object objParam) {
//Do something
}
}
}
namespace Generic {
class Program {
static void Main(string[] args) {
CommonMethod.ShowObject("object");
}
}
}

.Net Framework 2.0 以后 微软推出泛型

泛型方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/// 泛型方法  方法名称之后加<>  里面是类型参数  
/// 类型参数 , 实际上是一个类型声明
/// 延迟声明, 调用的时候指定 类型
/// 设计思想 --> 延迟声明, 推迟一切可以推迟的 一切能晚点再做的事儿, 就晚点再做 (咱不是很理解 ... 咱也不敢多问)
/// 编译器 编译时使用 占位符表示 `1 `2 表示有几个参数
/// CLR 运行是类型确定 替换掉占位符 生成多个类型的副本
/// 泛型方法效率 与普通方法一致 !!!

namespace Generic {
public class CommonMethod {
public static void Show<T>(T tparam) {
//Do something
}
}
}
namespace Generic {
class Program {
static void Main(string[] args) {
CommonMethod.ShowObject("object");
DateTime _curTime = DateTime.Now;
CommonMethod.Show<DateTime>(_curTime); // 可以省略 是<>内的 类型,
CommonMethod.Show(_curTime); //编译器提供的语法糖, 会自动推算 类型
int _intVal = 520;
CommonMethod.Show(_intVal);
}
}
}

泛型类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/// 泛型类 一个类 满足不同类型的需求
namespace Generic {
public class CommonMethod {
public class GenericClass<T> {

}
}
}
namespace Generic {
class Program {
static void Main(string[] args) {
CommonMethod.GenericClass<int> genericClass = new CommonMethod.GenericClass<int>(); //CLR中JIT编译时 会生生成各个类型的副本
}
}
}

泛型约束

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
namespace Generic {
public interface ISports {
void PingPang();
}
public interface IWork {
void Work();
}
public class People {
public int Id { get; set; }
public string Name { get; set; }
public void Hi() {

}
}
public class Chinese:People, IWork, ISports {
public void PingPang() {
throw new NotImplementedException();
}

public void Work() {
throw new NotImplementedException();
}
}

public class Hubei:Chinese {
public string ChangJiang { get; set; }
public void MaJiang() {
Console.WriteLine("打麻将!");
}
}
public class Bird {

}
public class Sparrow:Bird {

}
///out 协变 只能返回结果 不能做参数
public interface ICustomerListOut<out T> {
T Get();
// void Show(T t);
}
public class CustomerListOut<T>:ICustomerListOut<T> {
public T Get() {
return default;
}
}
/// in 逆变 只能做参数 不能做返回值
public interface ICustomerListIn<in T> {
//T Get();
void Show(T t);
}

public class CustomerListIn<T>:ICustomerListIn<T> {
public void Show(T t) {

}
}
}

/// 泛型约束 ,没有约束可能会出现类型安全问题
namespace Generic {
public class CommonMethod {
public static void Show<T>(T tparam)
where T : People //基类约束 密封类不能作为基类约束
{
Console.WriteLine($"id:{tparam.Id} name:{tparam.Name}");
}
public static void Show<T>(T tparam)
where T : ISports //接口约束
{
tparam.PingPang();
}
public static T Get<T>()
where T : class // 引用类型约束
{
return null;
}

public static T Get2<T>()
where T : struct // 值类型约束
{
return default; //default 是关键字儿 根据T的类型获取默认值
}
public static T Get3<T>()
where T : new() // 无参数构造函数约束
{
return new T();
}
}
}
///基类约束 调用时候 传递其基类或者子类
namespace Generic {
class Program {
static void Main(string[] args) {
Hubei hubei = new Hubei() {
Id = 123,
Name = "sanwu"
};
GenericConstraint.Show(hubei);
}
}
}

泛型缓存

1
2
3
4
5
6
7
8
9
10
11
/// 每个不同类型的T 都会生成新的副本
/// 适合不同类型, 缓存一份数据的场景,效率高
public class GenericClassCache<T> {
static GenericClassCache() {// 静态构造函数 程序启动只执行一次
_TypeTime = DateTime.Now.ToString("yyyy/MM/ddHH:mm:ss");
}
private static string _TypeTime = "";
public static string GetCache() {
return _TypeTime;
}
}

泛型逆变斜变

1
2
3
4
5
6
7
8
9
10
11
12
namespace Generic {
class Program {
static void Main(string[] args) {
List<Bird> birds = new List<Bird>(); //一堆鸟就是一堆鸟
//List<Bird> birds = new List<Sparrow>(); //一堆麻雀理论上也是一堆鸟, 语意上通过, 但是 语法上不通过
IEnumerable<Bird> birdsList = new List<Sparrow>(); //协变 让右边可以用子类 使用泛型导致基类与子类的父子关系失效 Out
ICustomerListOut<Bird> ListOut = new CustomerListOut<Sparrow>(); //协变
ICustomerListIn<Sparrow> ListIn= new CustomerListIn<Bird>(); //逆变 可以让右边用 父类 逆变之后

}
}
}
  • © 2019-2020 sanwu
  • PV: UV:

请我喝杯咖啡吧~

支付宝
微信