1.泛型的引入、泛型的声明
//测试obj和指定对象的性能对比
{
Stopwatch watch = new Stopwatch();
watch.Start();
for (int i = 0; i < 100_000_000; i++)
{
ShowInt(iValue);
}
watch.Stop();
commonSecond = watch.ElapsedMilliseconds;
}
{
Stopwatch watch = new Stopwatch();
watch.Start();
for (int i = 0; i < 100_000_000; i++)
{
ShowObject(iValue);
}
watch.Stop();
objectSecond = watch.ElapsedMilliseconds;
}
atch.ElapsedMilliseconds;
}
/// <summary>
/// 基类约束:
/// 泛型的类型参数,必须是People或者是People的子类
/// 否则无法传入;
/// 就可以把这个类型参数当做People来使用;
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="tParameter"></param>
public static void ShowGeneric<T>(T tParameter) where T : People
{
//Console.WriteLine($"This is {typeof(CommonMethod).Name},parameter={tParameter.GetType().Name},type={tParameter}");
Console.WriteLine($"People.Id={tParameter.Id}");
Console.WriteLine($"People.Name={tParameter.Name}"); //访问不了
}
///接口约束
///类型参数:必须实现这个接口,才能够传入进来;
///就可以把参数当成这个接口使用
public static void ShowGeneric<T>(T tParameter) where T : IWork
{
tParameter.Work();
}
///无参数构造函数约束
///传入的参数,必须包含一个无参数构造函数
///就可以直接new T 执行无参数构造函数~
public static void ShowGeneric<T>(T tParameter) where T : new()
{
T tt = new T();
}
///值类型约束
///必须要传入结构类型,否则无法传入的
public static void ShowGeneric<T>(T tParameter) where T : struct
{
}
///引用类型约束
///必须要传入引用类型,否则无法传入的
public static void ShowGeneric<T>(T tParameter) where T : class
{
}
///枚举约束
///要求传入的参数必须是一个枚举
public static void ShowGeneric<T>(T tParameter) where T : Enum
{
}
public static void ShowGenericNew<T,S,Y,Richard>(T tParameter) where T : struct
{
}
public static void ShowGenericNew2<T, S>(T tParameter) where T : class where S : struct
{
}
public enum ColorType
{
Red,
Green,
Blue
}
2.泛型的核心特点+原理,设计思想
有了约束---传入参数有了局部限制;
可以享有一些额外的权利~~
3.泛型方法,泛型类,泛型接口,泛型委托
4.泛型约束,泛型缓存,协变,逆变
泛型缓存
/// <summary>
/// 泛型缓存~
/// </summary>
public class GenericCacheTest
{
public static void Show()
{
//普通缓存
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine(DictionaryCache.GetCache<int>()); //GenericCacheInt
Thread.Sleep(10);
Console.WriteLine(DictionaryCache.GetCache<long>());// GenericCachelong
Thread.Sleep(10);
Console.WriteLine(DictionaryCache.GetCache<DateTime>());
Thread.Sleep(10);
Console.WriteLine(DictionaryCache.GetCache<string>());
Thread.Sleep(10);
Console.WriteLine(DictionaryCache.GetCache<GenericCacheTest>());
Thread.Sleep(10);
}
}
//泛型缓存--可以根据不同的类型生成一个新的类的副本;生合二老无数的副本;
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine(GenericCache<int>.GetCache()); //GenericCacheInt
Thread.Sleep(10);
Console.WriteLine(GenericCache<long>.GetCache());// GenericCachelong
Thread.Sleep(10);
Console.WriteLine(GenericCache<DateTime>.GetCache());
Thread.Sleep(10);
Console.WriteLine(GenericCache<string>.GetCache());
Thread.Sleep(10);
Console.WriteLine(GenericCache<GenericCacheTest>.GetCache());
Thread.Sleep(10);
}
}
}
}
/// <summary>
/// 字典缓存:静态属性常驻内存
/// </summary>
public class DictionaryCache
{
/// <summary>
/// 静态字典---常驻内存~ 只要程序进程不停止,就会一直保存数据在内存;
/// </summary>
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); //获取类的type 类型
if (!_TypeTimeDictionary.ContainsKey(type))
{
//写死的,生成数据; 使用当前这个type 作为key 保存到字典中去
_TypeTimeDictionary[type] = $"{typeof(T).FullName}_{DateTime.Now.ToString("yyyyMMddHHmmss.fff")}";
}
return _TypeTimeDictionary[type];
}
}
/// <summary>
///泛型缓存:
///本质就是泛型类---泛型缓存的应用--手写ORM----有应用~~
/// </summary>
/// <typeparam name="T"></typeparam>
public class GenericCache<T>
{
/// <summary>
///同一个类的静态构造函数在整个进程中,执行且只执行一次;
/// </summary>
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")}";
}
/// <summary>
/// 只缓存一个字符串
/// </summary>
private static string _TypeTime = "";
public static string GetCache()
{
return _TypeTime;
}
}
协变,逆变
//IEnumerable 也经常把他当成一个集合来用
//协变 就可以让右边用子类,能让左边用父类
//out:修饰类型参数;就可以让右边用子类,能让左边用父类
IEnumerable<Animal> animalList1 = new List<Animal>();
IEnumerable<Animal> animalList2 = new List<Cat>();
Func<Animal> func = new Func<Cat>(() => null);
//协变: Out 类型参数只能做返回值 ,不能做参数
//协变: Out 类型参数只能做返回值 ,不能做参数
ICustomerListOut<Animal> customerList1 = new CustomerListOut<Animal>();
ICustomerListOut<Animal> customerList2 = new CustomerListOut<Cat>(); //协变
/// <summary>
/// 动物
/// </summary>
public class Animal
{
public int Id { get; set; }
}
/// <summary>
/// Cat 猫
/// </summary>
public class Cat : Animal
{
public string Name { get; set; }
}
/// <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 协变 只能是返回结果 ,还是int 也是一种高级约束,避免出现问题
/// 泛型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) //t 是Cat的时候,这会儿你给我传递了一个Animal进来,子类做参数,但是传递了一个父类简历
{
}
}
public interface IMyList<in inT, out outT>
{
void Show(inT t);
outT Get();
outT Do(inT t);
}
/// <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);
}
}