泛型
大约 8 分钟约 2401 字
泛型
泛型引入
泛型声明
泛型的特点+原理
泛型的优势 ,核心设计
泛型约束
public static void ShowObject(object oParameter)
{
//Console.WriteLine("This is {0},parameter={1},type={2}",
// typeof(GenericConstraint), oParameter.GetType().Name, oParameter);
//传递一个实体对象:操作字段和数据
//问题:
//1.无法去属性字段--因为oParameter是Object; C#是强类型语言,编译时决定参数是什么类型;
//2.强制转换
//Console.WriteLine($"People.Id={oParameter.Id}");
//Console.WriteLine($"People.Name={oParameter.Name}");
People people = (People)oParameter;
Console.WriteLine($"People.Id={people.Id}");
Console.WriteLine($"People.Name={people.Name}");
}
/// <summary> /// 1.基类约束 /// a.就是把类型参数当做People /// b.调用---就可以传递Popple或者People的子类型 /// c.泛型约束:要么不让你进来,如果让你进来,就一定是没有问题 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="tParameter"></param> public static void ShowBase<T>(T tParameter) where T : People // ,ISports { Console.WriteLine($"People.Id={tParameter.Id}"); Console.WriteLine($"People.Name={tParameter.Name}"); //tParameter.Pingpang(); }
/// <summary> /// 接口约束: /// a.把这个T 当做ISports /// b.就只能传递ISports 这个接口或者是实现过这个接口的类 /// c.就可以增加功能,可以获取新的功能 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="tParameter"></param> public static void ShowInterface<T>(T tParameter) where T : ISports { tParameter.Pingpang(); }
/// <summary> /// 引用类型约束 /// a.就只能传递类型进来 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="tParameter"></param> public static void ShowClass<T>(T tParameter) where T : class { //T t = new T(); //因为T 可能没有无参数构造构造函数 }
/// <summary> /// 值类型约束 /// a.就只能传递值类型进来 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="tParameter"></param> public static void ShowStruct<T>(T tParameter) where T : struct { T t = new T(); }
/// <summary> /// 无参数构造函数约束 /// a. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="tParameter"></param> public static void ShowNew<T>(T tParameter) where T : new() { T t = new T(); }
/// <summary> /// 枚举约束 /// a.必须是个枚举才能够传递进来 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="tParameter"></param> public static void ShowEnum<T>(T tParameter) where T : Enum { }
泛型约束,泛型缓存
/// <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] = $"{typeof(T).FullName}_{DateTime.Now.ToString("yyyyMMddHHmmss.fff")}";
}
return _TypeTimeDictionary[type];
}
}
协变,逆变(是一种高级约束,是为了规避)
/// <summary>
/// out 协变covariant 修饰返回值
/// in 逆变contravariant 修饰传入参数
/// </summary>
public class ContravariantCovariance
{
public delegate T delegateTest<T>(T t);
/// <summary>
/// 协变逆变 只针对于泛型接口和泛型委托的
/// </summary>
public static void Show()
{
{
Animal animal1 = null;
animal1 = new Animal();
Cat cat1 = null;
cat1 = new Cat();
//任何子类都可以使用父类来声明
Animal animal2 = null;
animal2 = new Cat();
///不一定--
//Cat cat2 = null;
//cat2 = new Animal();
//Cat cat2 = null;
//cat2 = (Cat)(new Animal());
}
{
List<Animal> animalList1 = null;
animalList1 = new List<Animal>();
//一只猫是一个动物
//一堆猫 却不是一堆动物---从口语上来说,有点不符合人类的思维逻辑;
//Why?---二者没有父子级关系;当然不能替换; 这是C#语法所决定的
//泛型存在不友好,不协调的地方;
//不能在左边用父类;
//List<Animal> animalList2 = null; //--- List<Animal> 针对于Animal的类
//animalList2 = new List<Cat>(); //--- List<Cat>针对于Cat的类
// List<Animal> animalList3 = new List<Cat>().Select(c => (Animal)c).ToList();
}
//就引入了协变和逆变
{
//IEnumerable 也经常把他当成一个集合来用
//协变 就可以让右边用子类,能让左边用父类
//out:修饰类型参数;就可以让右边用子类,能让左边用父类
IEnumerable<Animal> animalList1 = new List<Animal>();
IEnumerable<Animal> animalList2 = new List<Cat>();
Func<Animal> func = new Func<Cat>(() => null);
//协变: Out 类型参数只能做返回值 ,不能做参数
ICustomerListOut<Animal> customerList1 = new CustomerListOut<Animal>();
ICustomerListOut<Animal> customerList2 = new CustomerListOut<Cat>(); //协变
//customerList2.Show(new Animal());
//customerList2.Show(new Cat());
}
{//逆变 In 只能做参数 ,不能做返回值
//逆变:就可以让右边用父类;左边用子类
ICustomerListIn<Cat> customerList2 = new CustomerListIn<Cat>();
ICustomerListIn<Cat> customerList1 = new CustomerListIn<Animal>();
//逆变: In 类型参数只能做参数 ,不能做返回值
//customerList1.Get();//调用的是接口的方法
//customerList1.Get(); //返回的一定是一个Cat 或者是Cat 的子类;
//因为通过接口在调用方法的时候只能返回一个Cat,
}
//协变逆变的存在,就是为了满足常规场景添加一个避开风险的约束;
{
IMyList<Cat, Animal> myList1 = new MyList<Cat, Animal>();
IMyList<Cat, Animal> myList2 = new MyList<Cat, Cat>();//协变
IMyList<Cat, Animal> myList3 = new MyList<Animal, Animal>();//逆变
IMyList<Cat, Animal> myList4 = new MyList<Animal, Cat>();//协变+逆变
}
//为什么呢?
//如果没有协变逆变;会如何?
{
}
}
}
public class Test : ICustomerListOut<Animal>
{
public Animal Get()
{
return new Cat();
}
public void Show(Animal t)
{
}
}
public class Test2 : ICustomerListOut<Cat>
{
public Cat Get()
{
throw new NotImplementedException();
}
public void Show(Cat t)
{
throw new NotImplementedException();
}
}
/// <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);
}
}