原理图
class Program
{
static void Main(string[] args)
{
try
{
int iValue = 123;
string sValue = "456";
DateTime dtValue = DateTime.Now;
object oValue = "789";
Console.WriteLine("***********************普通方法重载***********************");
CommonMethod.ShowInt(iValue);
CommonMethod.ShowString(sValue);
CommonMethod.ShowDateTime(dtValue);
Console.WriteLine("***********************Object对象接受(拆装箱)***********************");
CommonMethod.ShowObject(oValue);
CommonMethod.ShowObject(iValue);
CommonMethod.ShowObject(sValue);
CommonMethod.ShowObject(dtValue);
Console.WriteLine("***********************泛型***********************");
// 泛型只有:泛型方法、泛型类、泛型接口、泛型委托
//泛型方法调用的时候,需要加上<>,而且需要指定具体的类型、指定的类型和传入的参数类型保持一致。
CommonMethod.Show(iValue); //如果类型参数,可以通过参数类型推导出来,那么就可以省略
/* CommonMethod.Show<int>(sValue);*/// 因为类型错了
CommonMethod.Show(sValue);
CommonMethod.Show<DateTime>(dtValue);
CommonMethod.Show<object>(oValue);
Console.WriteLine("***********************泛型缓存***********************");
GenericCacheTest.Show();
Console.WriteLine("***********************泛型约束***********************");
//无约束情况
People people = new People()
{
Id = 123,
Name = "人民"
};
Chinese chinese = new Chinese()
{
Id = 234,
Name = "中国"
};
Hubei hubei = new Hubei()
{
Id = 345,
Name = "湖北"
};
Japanese japanese = new Japanese()
{
Id = 678,
Name = "日报"
};
// Object 方法因为可以出入任何类型,没有限制,如果传入的类型不匹配,就会发生异常(类型安全问题)
//GenericConstraint.ShowObject(people);
//GenericConstraint.ShowObject(chinese);
//GenericConstraint.ShowObject(hubei);
//GenericConstraint.ShowObject(japanese);
//GenericConstraint.Show(people);
//GenericConstraint.Show(chinese);
//GenericConstraint.Show(hubei);
//GenericConstraint.Show(japanese);
//有约束情况
// GenericConstraint.GenericShow(123);
GenericConstraint.GenericShow(people);
GenericConstraint.GenericShow(chinese);
GenericConstraint.GenericShow(hubei);
GenericConstraint.GenericShow(japanese);//
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.Read();
}
}
对应的类
public class CommonMethod
{
/// <summary>
/// 打印个int值
/// </summary>
/// <param name="iParameter"></param>
public static void ShowInt(int iParameter)
{
Console.WriteLine("This is {0},parameter={1},type={2}",
typeof(CommonMethod).Name, iParameter.GetType().Name, iParameter);
}
/// <summary>
/// 打印个string值
/// </summary>
/// <param name="sParameter"></param>
public static void ShowString(string sParameter)
{
Console.WriteLine("This is {0},parameter={1},type={2}",
typeof(CommonMethod).Name, sParameter.GetType().Name, sParameter);
}
/// <summary>
/// 打印个DateTime值
/// </summary>
/// <param name="oParameter"></param>
public static void ShowDateTime(DateTime dtParameter)
{
Console.WriteLine("This is {0},parameter={1},type={2}",
typeof(CommonMethod).Name, dtParameter.GetType().Name, dtParameter);
}
/// <summary>
///为什么用object 作为参数类型,调用的时候,可以把任何类型都传进来
///
///C#: 任何父类出现的地方 都可以用子类代替;
///Object类型是一切类型的父类
///
///Object 出现的都可以让任何类型传进来
///
/// 但是:有2个问题
/// 性能问题:会出现装箱和拆箱;
/// 类型安全问题。
/// </summary>
/// <param name="oParameter"></param>
public static void ShowObject(object oParameter)
{
Console.WriteLine("This is {0},parameter={1},type={2}",
typeof(CommonMethod), oParameter.GetType().Name, oParameter);
}
/// <summary>
/// 泛型方法:需要在方法名的后面带一个<>,需要定义T, T是什么呢? 不知道,
/// T:类型参数,只是一个占位符,类型在声明其实不确定,在调用的时候,确定类型。
///
/// 延迟声明,推迟一切可以推迟的,事情能晚点做就晚点做。
/// 在使用的时候,需要指定明确的类型
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="tParameter"></param>
public static void Show<T>(T tParameter)
{
Console.WriteLine("This is {0},parameter={1},type={2}",
typeof(CommonMethod), tParameter.GetType().Name, tParameter);
}
}
public class GenericCacheTest
{
public static void Show()
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine(GenericCache<int>.GetCache());
Thread.Sleep(10);
Console.WriteLine(GenericCache<long>.GetCache());
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
{
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(Type);
if (!_TypeTimeDictionary.ContainsKey(type))
{
_TypeTimeDictionary[type] = string.Format("{0}_{1}", typeof(T).FullName, DateTime.Now.ToString("yyyyMMddHHmmss.fff"));
}
return _TypeTimeDictionary[type];
}
}
/// <summary>
///泛型缓存: 会根据传入的不同类型,分别生成不同的副本
///
/// 可以接受任何类型,需要根据不同类型缓存一部分数据就可以使用,效率更好
/// </summary>
/// <typeparam name="T"></typeparam>
public class GenericCache<T>
{
static GenericCache()
{
Console.WriteLine("This is GenericCache 静态构造函数");
_TypeTime = string.Format("{0}_{1}", typeof(T).FullName, DateTime.Now.ToString("yyyyMMddHHmmss.fff"));
}
private static string _TypeTime = "";
public static string GetCache()
{
return _TypeTime;
}
}
/// <summary>
/// 泛型约束
/// </summary>
public class GenericConstraint
{
public static void ShowObject(object oParameter)
{
// Console.WriteLine(oParameter.Id);// 编译器就报错,因为C# 是强类型的语言,在编译的时候就要确定类型
People people = (People)oParameter;
Console.WriteLine(people.Id);
Console.WriteLine("This is {0},parameter={1},type={2}",
typeof(CommonMethod), oParameter.GetType().Name, oParameter);
}
public static void Show<T>(T tParameter)
// where T : People //基类约束,你只能是一个People ,所以这里参数只能传入People或者People子类
where T : ISports // 接口约束
{
//Console.WriteLine(tParameter.Id); //又报错了
// Console.WriteLine(tParameter.Id);
// 加了 T : ISports约束以后,发现不能访问Id
tParameter.Pingpang();
Console.WriteLine("This is {0},parameter={1},type={2}",
typeof(CommonMethod), tParameter.GetType().Name, tParameter);
}
public static void GenericShow<T>(T tParameter)
// where T : class // 引用类型约束 就只能传入引用类型的参数
// where T : struct
// where T : new()// 无参数构造偶函数约束
{
Console.WriteLine("This is {0},parameter={1},type={2}",
typeof(CommonMethod), tParameter.GetType().Name, tParameter);
}
public static void GenericShow1<T>(T tParameter)
where T : class, new() // 泛型约束可以结合使用 ,用逗号分隔就OK
{
Console.WriteLine("This is {0},parameter={1},type={2}",
typeof(CommonMethod), tParameter.GetType().Name, tParameter);
}
public static T GenericShow2<T>()
{
return default(T); // default关键字
}
}
协变和逆变
/// <summary>
/// 只能放在接口或者委托的泛型参数前面
/// out 协变covariant 修饰返回值
/// in 逆变contravariant 修饰传入参数
/// </summary>
public class CCTest
{
public static void Show()
{
{
Bird bird1 = new Bird();
Bird bird2 = new Sparrow();
Sparrow sparrow1 = new Sparrow();
/* Sparrow sparrow2 = new Bird()*/
;
}
{
List<Bird> birdList1 = new List<Bird>();
//List<Bird> birdList2 = new List<Sparrow>();
//难道一组麻雀不是一组鸟吗?
//List<Bird> 是一个类, List<Sparrow> 是另外一个类,二者没有继承
List<Bird> birdList3 = new List<Sparrow>().Select(c => (Bird)c).ToList();
}
//泛型在使用的时候,会存在不和谐的地方
// 协变和逆变 都是在泛型中才有,在泛型接口 或者泛型委托才有
{//out修改类型参数,协变:可以让右边使用子类
// 使用协变时候,可以把子类放在右边,这才是泛型该有的样子
IEnumerable<Bird> birdList1 = new List<Bird>();
IEnumerable<Bird> birdList2 = new List<Sparrow>(); //为什么可以写?
ICustomerListOut<Bird> customerList1 = new CustomerListOut<Bird>();
ICustomerListOut<Bird> customerList2 = new CustomerListOut<Sparrow>();
}
{//逆变
//int修改类型参数,逆变:可以让右边使用父类
// 类型参数只能作为参数 ,不能作为返回值
ICustomerListIn<Sparrow> customerList2 = new CustomerListIn<Sparrow>();
ICustomerListIn<Sparrow> customerList1 = new CustomerListIn<Bird>();
customerList1.Show(new Sparrow());
ICustomerListIn<Bird> birdList1 = new CustomerListIn<Bird>();
birdList1.Show(new Sparrow());
birdList1.Show(new Bird());
}
{
IMyList<Sparrow, Bird> myList1 = new MyList<Sparrow, Bird>();
IMyList<Sparrow, Bird> myList2 = new MyList<Sparrow, Sparrow>();//协变
IMyList<Sparrow, Bird> myList3 = new MyList<Bird, Bird>();//逆变
IMyList<Sparrow, Bird> myList4 = new MyList<Bird, Sparrow>();//协变+逆变
}
//完全能理清楚 刷个1
//能清楚80% 2 60% 3
}
}
public class Bird
{
public int Id { get; set; }
}
public class Sparrow : Bird
{
public string Name { get; set; }
}
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);
//inT Get1();
}
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);
}
}