任何父类出现的地方,都可以用子类来代替
C# 被电脑执行的过程
C# ==> 编译器编译代码成为 中间语言(IL)包 .dll文件或者.exe ==> CLR将中间语言转换为机器码 ==> 电脑执行
泛型
泛型是 .netforework 2.0 出现的,在之前编译器无法识别尖括号,所以编译器也进行了升级,在编译时由于 T 还没有确定会由占位符替代.
如下示例:
Console.WriteLine(typeof(List<>) );
Console.WriteLine(typeof(Dictionary<,>));
Console.WriteLine("===============================");
Console.WriteLine(typeof(List<int>));
Console.WriteLine(typeof(Dictionary<string,int>));
结果:
System.Collections.Generic.List`1[T]
System.Collections.Generic.Dictionary`2[TKey,TValue]
===============================
System.Collections.Generic.List`1[System.Int32]
System.Collections.Generic.Dictionary`2[System.String,System.Int32]
其中 `1 代表有几个类型参数,`2同理
在2.0 .netframework 的编译器可以识别 <> 后
CLR (公共语言运行时) 还不能认识 占位符 是什么意思,所以升级CLR
在代码运行时,知道了确切的类型,会将占位符替换掉
所以泛型不是一个简单的语法糖,是通过框架升级来支撑的
装箱/泛型/普通方法的性能:
代码:
class Monitor
{
public static void Show()
{
Console.WriteLine("********************Monitor*****************");
{
int iValue = 12345;
long commonSecond = 0;
long objectSecond = 0;
long genericSecond = 0;
{
Stopwatch watch = new Stopwatch();
watch.Start();
for (int i = 0; i < 100000000; i++)
{
ShowInt(iValue);
}
watch.Stop();
commonSecond = watch.ElapsedMilliseconds;
}
{
Stopwatch watch = new Stopwatch();
watch.Start();
for (int i = 0; i < 100000000; i++)
{
ShowObject(iValue);
}
watch.Stop();
objectSecond = watch.ElapsedMilliseconds;
}
{
Stopwatch watch = new Stopwatch();
watch.Start();
for (int i = 0; i < 100000000; i++)
{
Show(iValue);
}
watch.Stop();
genericSecond = watch.ElapsedMilliseconds;
}
Console.WriteLine("int类型: {0},object : {1},泛型 : {2}",
commonSecond, objectSecond, genericSecond
);
Console.ReadKey();
}
}
public static void ShowInt(int tParameter)
{
}
public static void ShowObject(object tParameter)
{
}
public static void Show<T>(T tParameter)
{
}
}
show方法执行结果: Object 方法耗时大约是 泛型和普通方法的两倍, 普通方法和泛型是处于同一级别的
以此证明装箱拆箱是相对耗费性能等,
而泛型方法不仅性能好还可以适应多种类型
泛型方法的参数默认值
public static void Test<T>(T pram = default(T))
{
}
WebService , WCF 都不可以使用泛型 ,为什么?
表面解释:因为它们是跨语言的,而其他语言可能没有泛型概念
深层次解释: 因为服务在发布前是必须要确定的
子类继承 泛型父类时需要指定类型/或者自己也是泛型
class Monitor:GenericCache<int>
{
public class Detial<T, R> : product<T>, ICar<R>
我的多年以来的错误: 我以为普通类中的静态方法是只能被自己使用的,然而不是,普通类中的静态方法也是
类名.方法名 如 ClassName.GetDate()
泛型类中的静态方法是通过
静态类<T> 方法名 ClassName<int>.GetDate()
泛型约束 Generic Constraint :
基类约束,
接口约束,
引用类型约束,
值类型约束,
无参构造函数约束
public class product<T>
{
}
interface ICar<R> where R : product<int>
{
void OpenDoor(R data);
R OpenDoors(R data);
}
如果约束时泛型类,需要指明类型
public T product<T>( )
//where T : class //引用类型约束
//where T : struct //值类型约束
// where T : new() //无参构造函数约束
{
//return null; //只有引用类型才可以为null
//return default(T); //default() 可以用于所有类型
//return new T(); //添加无参构造函数约束才可以这样写
}
将 密封类 作为约束是 不行的 因为不会存在子类,所以搞泛型没有意义
泛型扩展:泛型缓存
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 2; i++)
{
Console.WriteLine(GenericCache<int>.GetCache());
Thread.Sleep(1000);
Console.WriteLine(GenericCache<string>.GetCache());
Thread.Sleep(1000);
Console.WriteLine(GenericCache<Boolean>.GetCache());
Thread.Sleep(1000);
Console.WriteLine(GenericCache<DateTime>.GetCache());
}
}
}
public class GenericCache<T>
{
static GenericCache()
{
Console.WriteLine("this is DictionaryCache 静态构造函数" );
_TypeTIme = string.Format("{0}_{1}", typeof(T).FullName,
DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
}
private static string _TypeTIme = "";
public static string GetCache()
{
return _TypeTIme;
}
}
第一次循环截图: 会进入4次构造函数,
结果:执行构造函数后,会一直存在着,不会被回收,下一次就直接拿取数据