1.泛型:宽泛的——不确定的; 型:类型——不确定的类型
2.调用普通方法的时候,参数类型在声明时就确定了,调用按照类型传递参数即可
3.如果可以通过参数推导出来则可以省略尖括号
为什么不能使用object的替代泛型
a.性能问题——装箱拆箱
b.类型安全问题
1.泛型方法:在一个方法名称后面多了一个尖括号,尖括号中有占位符
2.延迟声明:声明的时候,只是给一个占位符T T是什么类型?你调用的时候是什么,你说什么就是什么
3.占位符 T-类型参数——类型变量
4.类型参数当做方法的参数的时候,明确参数类型
泛型不是语法糖泛型是由框架升级支持的,使用时CLR需要支持泛型
1.泛型方法——可以一个方法满足不同的类型需求
2.泛型类——可以一个类满足不同类型的需求
3.泛型接口——可以一个接口满足不同类型的需求
4.泛型委托——可以一个委托满足不同类型的需求
object类型安全问题:向接收object类型的方法传递类,接收object类型方法中可能会有对类的转换,但是接口没有约束,会导致隐患。
///
/// 基类约束
/// 类型参数设定为people类型
/// 调用时就可以传递People或者People的子类型
///
///
///
public static void Show(T tParameter) where T : People
{
Console.WriteLine(tParameter.Id);
Console.WriteLine(tParameter.Name);
}
///
/// 接口约束
/// a.把这个T当作ISports
/// b.就只能传递ISporys 这个接口或者时实现过这个接口的类
/// c.可以获取使用接口的功能
///
///
///
public static void Show(T tParameter) where T : ISports
{
tParameter.Pingpang();
}
1 ///
2 /// 引用类型约束
3 /// a.就只能传递引用类型
4 ///
5 ///
6 ///
7 public static void ShowClass(T tParameter) where T : class
8 {
9 }
///
/// 值类型约束
/// a.就只能传递值类型
///
///
///
public static void ShowStruct(T tParameter) where T : struct
{
}
///
/// 无参数构造函数约束
/// a.只能传输无参数构造类
///
///
///
public static void ShowNew(T tParameter) where T : new()
{
T t = new T();
}
///
/// 枚举约束
/// a.只能传输无参数构造类
///
///
///
public static void ShowEnum(T tParameter) where T : Enum
{
}
///
/// 限定泛型的继承关系
/// 要不是同一类型要不是继承关系
/// T继承S
///
///
///
public static void ShowParent(T tParameter) where T : S
{
}
可以根据不同的类型生成一个新的类的副本;
///
///泛型缓存:
///
///
public class GenericCache
{
static GenericCache()
{
Console.WriteLine("This is GenericCache 静态构造函数");
//_TypeTime = string.Format("{0}_{1}", typeof(T).FullName, DateTime.Now.ToString("yyyyMMddHHmmss.fff"));
_TypeTime = $"{typeof(T).FullName}_{DateTime.Now.ToString("yyyyMMddHHmmss.fff")}";
}
private static string _TypeTime = "";
public static string GetCache()
{
return _TypeTime;
}
}
调用
Console.WriteLine(GenericCache.GetCache()); //GenericCacheInt
Console.WriteLine(GenericCache.GetCache());// GenericCachelong
Console.WriteLine(GenericCache.GetCache());
Console.WriteLine(GenericCache.GetCache());
Console.WriteLine(GenericCache.GetCache());
协变和逆变只支持泛型接口和泛型委托
协变可以让右边使用子类,左边使用父类。 Out类型参数只能做返回值,不能做参数
逆变可以让右边用父类,左边用子类。in类型参数只能做参数,不能作为返回值
协变逆变的存在就是为了满足常规场景添加一个避开风险的约束
public interface ICustomerListOut
{
T Get();
void Show(T t);
}
CustomerListOut实现这个接口
public class CustomerListOut : ICustomerListOut
{
public T Get()
{
return default(T);
}
public void Show(T t)
{
}
}
在T为Animal时传入了Cat,就会发生错误。
所以才需要用in out来进行约束,来限定,在此类中限定out后,T就不能作为参数使用,就规避了出现错误的可能性。
///
/// T 就只能做参数 不能做返回值
///
///
public interface ICustomerListIn
{
//T Get();
void Show(T t);
}
public class CustomerListIn : ICustomerListIn
{
//public T Get()
//{
// return default(T);
//}
public void Show(T t)
{
}
}
///
/// out 协变 只能是返回结果 ,还是int 也是一种高级约束,避免出现问题
/// 泛型T 就只能做返回值; 不能做参数;
///
///
public interface ICustomerListOut
{
T Get();
//void Show(T t);
}
public class CustomerListOut : ICustomerListOut
{
public T Get()
{
return default(T);
}
public void Show(T t) //t 是Cat的时候,这会儿你给我传递了一个Animal进来,子类做参数,但是传递了一个父类简历
{
}
}