泛型大讲解
1. 什么是泛型?
就在在声明的时候,带上一个<>,指定类型参数,调用的时候指定类型调用---泛型;
概念
可直接跳过的概念。
-
泛型方法:一个方法满足了不同类型的需求;
-
泛型类:一个类满足不同类的需求;
-
泛型接口:一个接口满足不同接口的需求;
-
泛型委托:一个委托满足不同委托的需求;
Object是一切类型的父类。
任何父类出现的地方都可以用子类来代替。
举例
下面代码段,这就是常用的泛型<>;就是说在传类型以前他可以是任何类型。传int或类等类或结构类型的时候就限定了他的类型。
List<int> intlist = new List<int>();
List<string> stringlist = new List<string>();
2. 如何声明和使用泛型?
代码示例与效果
public class Monitor
{
public static void Show()
{
Show<int>(1);
}
private static void Show<T>(T tParameter)
{
Console.WriteLine($"调用第一次泛型{tParameter}");
}
}
3. 泛型的延迟思想?
尽量靠后实现具体
写代码时尽可能把实际的实现内容往后靠,这样一个朦胧的程序使我们有了多种可能。比如就可以在我们在调用的时候再约定它该是一个什么参数。
4. 泛型的好处和原理?
好处
- 一个方法可以满足不同类型的需求。(某个类中需要传参数,int,string等,不能每个不同类型参数要新写一个方法。无法实现高可用与可扩展,那么就可以用到泛型。当然此处也可使用Object但是速度会慢两倍之多,因为涉及到装箱拆箱)
装箱 就是把“值类型”转换成“引用类型”(Object);
拆箱 就是把“引用类型”转换成“值类型”; - 性能高(他的速度和直接使用int,string等结构或类时速度一样)。
原理与概念
泛型在编译之后,泛型参数会生成占位符2
最终会根据调用生成不同的普通方法;
泛型在.NetFramework2已经出来了;
泛型不是一个语法糖(语法糖指添加某种语法,对语言的功能并没有影响,方便程序员使用);
泛型—编译器升级+CLR升级
泛型是框架的升级所支持的;
5. 泛型类、方法、接口、委托?
概念
- 泛型方法:一个方法满足了不同类型的需求;
- 泛型类:一个类满足不同类的需求;
- 泛型接口:一个接口满足不同接口的需求;
- 泛型委托:一个委托满足不同委托的需求;
6. 泛型约束,泛型缓存?
约束解决什么
传入的参数在处理的时候,可能会出现真实类型不匹配的情况。
泛型约束分类
- 基类约束:约束这个T 就是People; 就约束只能传递People或者People的子类
- 接口约束:约束这个T 是ISports接口的实现类 可以调用接口中的方法—权利;调用的时候–只能传递实现过这个接口的类进入–义务
- 引用类型约束:只能传入引用类型的参数
- 值类型约束:只能传入值类型的参数
- 无参数构造函数约束:传入的参数必须有拥有一个无参数构造函数只需要在限定类型处写:new()
约束如何写
通过观察如下代码段。仅需要在参数后增加
where T(参数类型):(限定类型)
限定类型可以为
/// <summary>
/// 值类型约束
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="tParameter"></param>
public static T ShowStruct<T>(T tParameter)
where T : struct
{
return default(T); //任何类型都可以,default(T) 根据实际的调用类来生成默认值;
}
/// <summary>
///引用类型约束
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="tParameter"></param>
public static T ShowClass<T>(T tParameter)
where T : class
{
return default(T); //任何类型都可以,default(T) 根据实际的调用类来生成默认值;
}
缓存应用场景
举例子:比如要进行根据实体类获取增删改查语句。这时候就可以用到缓存放起来。
/// <summary>
/// 字典缓存:静态属性常驻内存
/// </summary>
public class DictionaryCache
{
private static Dictionary<Type, string> _TypeTimeDictionary = null;
static DictionaryCache()
{
Console.WriteLine("This is DictionaryCache 静态构造函数");
_TypeTimeDictionary = new Dictionary<Type, string>();
}
public static string GetCache<T>()
{
Type type = typeof(T);
if (!_TypeTimeDictionary.ContainsKey(type))
{
//_TypeTimeDictionary[type] = string.Format("{0}_{1}", typeof(T).FullName, DateTime.Now.ToString("yyyyMMddHHmmss.fff"));
_TypeTimeDictionary[type] = $"{typeof(T).FullName}_{DateTime.Now.ToString("yyyyMMddHHmmss.fff")}";
}
return _TypeTimeDictionary[type];
}
}
7. 协变逆变?
概念
协变 协变: Out 只能做返回值 ,不能做参数,可以让右边使用子类
逆变 逆变: in 只能做参数 ,不能做返回值,可以让右边使用父类
使用
如下代码块会出错,因为我们指定泛型的类型为Animal,实例的时候传入Cat就会出错。
注:Cat是继承自Animal
#region 协变 逆变例子
/// <summary>
/// T 就只能做参数 不能做返回值
/// </summary>
/// <typeparam name="T"></typeparam>
public interface ICustomerListIn<in T>
{
//T Get();
void Show(T t);
}
public class CustomerListIn<T> : ICustomerListIn<T>
{
//public T Get()
//{
// return default(T);
//}
public void Show(T t)
{
}
}
/// <summary>
/// out 协变 只能是返回结果
/// 泛型T 就只能做返回值; 不能做参数;
/// </summary>
/// <typeparam name="T"></typeparam>
public interface ICustomerListOut<out T>
{
T Get();
//void Show(T t);
}
public class CustomerListOut<T> : ICustomerListOut<T>
{
public T Get()
{
return default(T);
}
//public void Show(T t)
//{
//}
}
public interface IMyList<in inT, out outT>
{
void Show(inT t);
outT Get();
outT Do(inT t);
out 只能是返回值 in只能是参数
//void Show1(outT t);//左边声明是父类---右边实例化是子类 new MyList<Cat, Cat>()---outT是cat--方法调用时以左边为准,传递的是animal的子类-狗
//inT Get1();
}
/// <summary>
/// out 协变 只能是返回结果
/// in 逆变 只能是参数
///
/// </summary>
/// <typeparam name="T1"></typeparam>
/// <typeparam name="T2"></typeparam>
public class MyList<T1, T2> : IMyList<T1, T2>
{
public void Show(T1 t)
{
Console.WriteLine(t.GetType().Name);
}
public T2 Get()
{
Console.WriteLine(typeof(T2).Name);
return default(T2);
}
public T2 Do(T1 t)
{
Console.WriteLine(t.GetType().Name);
Console.WriteLine(typeof(T2).Name);
return default(T2);
}
}
#endregion
8. 意外收获?
收获
哈哈哈哈,新学到一个拼字符串的方式。
在拼接字符串的最前加$中间需要加什么参数打一个{}在里边放参数就可以了
Console.WriteLine($"调用第一次泛型{tParameter}");