1. 泛型Generic
1.1 引入泛型:延迟声明
泛型方法声明时,并未写死类型,在调用的时候再指定类型。
延迟声明:推迟一切可以推迟的。
1.2 如何声明和使用泛型
泛型方法:方法名称后面加上尖括号,里面是类型参数
类型参数实际上就是一个类型T声明,方法就可以用这个类型T了。
如下所示:
public static void Show
{
Console.WriteLine($"This is {typeof(CustomMethod)},paramater={t.GetType().Name},value={t}");
}
1.3 泛型的好处和原理
泛型方法性能跟普通方法一致,泛型声明方法时,并未写死类型,T是什么类型,只有在调用的时候才知道,一个方法能满足不同类型。
1.4 泛型类、泛型方法、泛型接口、泛型委托
1.4.1 泛型类型
一个类满足不同类型的需求
具体如下:
public class BaseModel
{
public int Id { get; set; }
}
public class GenericClass
where T:BaseModel//为泛型基类约束
{
}
1.4.2 泛型方法
一个方法满足不同类型的需求
具体如下:
public static void Show
{
Console.WriteLine($"This is {typeof(CustomMethod)},paramater={t.GetType().Name},value={t}");
}
1.4.3 泛型接口
一个接口满足不同类型的需求
//泛型接口
public interface IGenericInterface
{
public void SayHi(T t);
}
1.4.4 泛型委托
一个委托满足不同类型的需求
public delegate void Do
1.5 泛型约束
没有约束,泛型会很局限。主要有5中泛型的约束。如下:
1.5.1 基类约束
Where T:BaseModel
可以把BaseModel当作基类
只有该类型的对象或从该类型派生出的对象,可被用作类型参数。(密封类约束的不行,因为没有意义。)
//基类
public class BaseModel
{
public int Id { get; set; }
}
//泛型类
public class GenericClass
where T:BaseModel//为泛型基类约束
{
}
调用:
GenericConstraint.Show
1.5.2 引用类型约束
//引用类型约束
public static T Get
{
return default(T);//default是关键字,根据类型T返回对应的默认值
}
调用:
GenericConstraint.Get
1.5.3 值类型约束
//值类型约束
Public static D GetD
{
return default(D);
}
调用:
GenericConstraint.GetD
1.5.4 无参数构造函数
//无参数构造函数约束
Public static S GetS()
where S: new()//无餐构造函数约束
{
return new S();
}
调用:
GenericConstraint.GetS
1.5.5 接口约束
//接口约束
public static void Show2
{
t.Basketball();
}
调用:
GenericConstraint.Show2
1.6 协变、逆变
所谓协变、逆变都是跟泛型有关的(多用在接口)。
1.6.1 协变
修饰返回值
让右边用子类,让泛型用起来更方便(子类转父类)
Out修饰,协变后只能是返回结果,不能做参数
IEnumerable
//out 协变,只能是返回结果(子类转父类)
public interface ICustomerListOut
{
T Get();
}
public class CustomerListOut
{
public T Get()
{
return default(T);
}
}
ICustomerListOut
Func
IEnumerable
1.6.2 逆变
修饰传入参数
让右边可以用父类,让泛型用起来更方便(父类转子类)
In修饰,逆变后只能当作参数
//in 逆变 只能是输入参数(父类转子类)
public interface ICustomerListIn
{
void Show(T t);
}
public class CustomerListIn
{
public void Show(T t)
{
Console.WriteLine(t.GetType().Name);
}
}
//逆变
ICustomerListIn
Action
public interface IMyList
{
void Show(inT t);
outT Get();
outT Do(inT t);
}
public class MyList
{
public void Show(T t)
{
Console.WriteLine(t.GetType().Name);
}
public T1 Get()
{
Console.WriteLine(typeof(T1).Name);
return default(T1);
}
public T1 Do(T t)
{
Console.WriteLine(t.GetType().Name);
Console.WriteLine(typeof(T1).Name);
return default(T1);
}
}
IMyList
IMyList
IMyList
IMyList
1.7 泛型缓存
泛型缓存,每个类型都会生成一个不同的副本(适合不同类型需要缓存一份数据的场景)
public class GenericCache
{
private static string _TypeTime = "";
static GenericCache()
{
Console.WriteLine("This is GenericCache 静态构造函数");
_TypeTime = $"{typeof(T).FullName}_{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}";
}
public static string GetCache()
{
return _TypeTime;
}
}
///
/// 字典缓存:静态属性常驻内存
///
public class DictionaryCache
{
private static Dictionary
static DictionaryCache()
{
Console.WriteLine("This is DictionaryCache 静态构造函数");
_TypeTimeDictionary = new Dictionary
}
public static string GetCache
{
Type type = typeof(Type);
if (!_TypeTimeDictionary.ContainsKey(type))
_TypeTimeDictionary[type] = $"{typeof(T).FullName}_{DateTime.Now.ToString("yyyy-MM-dd HH mm:ss")}";
return _TypeTimeDictionary[type];
}
}