一 啥是泛型。
创建一个控制台项目 (过程略。)
1 先从体验一个类 showX 参数类型不同,需要写不同的方法
//准备一个类。
public class CommonMethod
{
public static void showInt(int parameter)
{
Console.WriteLine("This is {0}, paramter={1}, type = {2}",
typeof(CommonMethod).Name, parameter.GetType().Name, parameter
);
}
public static void showString(string parameter)
{
Console.WriteLine("This is {0}, paramter={1}, type = {2}",
typeof(CommonMethod).Name, parameter.GetType().Name, parameter
);
}
public static void showDateTime(DateTime parameter)
{
Console.WriteLine("This is {0}, paramter={1}, type = {2}",
typeof(CommonMethod).Name, parameter.GetType().Name, parameter
);
}
}
//program.cs 中使用。
CommonMethod.showInt(123);
CommonMethod.showString("hello world");
CommonMethod.showDateTime(DateTime.Now);
运行后效果。
2. 1.0 时代,不同的类型,要写多个,很麻烦,于是有优化的方法 。
public class CommonMethod
{
...
public static void showObj(object oParamter)
{
Console.WriteLine("showObj:This is {0}, paramter={1}, type = {2}",
typeof(CommonMethod).Name, oParamter.GetType().Name, oParamter
);
}
}
//program.cs 中使用。
CommonMethod.showObj(123);
CommonMethod.showObj("hello world");
CommonMethod.showObj(DateTime.Now);
运行后效果。
3 使用泛型写法。
public class CommonMethod
{
...
public static void show<T>(T t)
{
Console.WriteLine("show:This is {0}, paramter={1}, type = {2}",
typeof(CommonMethod).Name, t.GetType().Name, t
);
}
}
//program.cs 中使用。
CommonMethod.show(123);
CommonMethod.show("hello world");
CommonMethod.show(DateTime.Now);
运行后效果。
简单的说, 使用泛型 让你写与任何数据类型一起工作的类与方法 。
- 2.0 推出的新语法。 声明的时候不指定,调用的时候指定。
- 是一种延迟声明: 把参数类型的声明推迟到调用。
- 不是语法糖,是由框架升级提供的功能 (编译器支持 编译时为占位符 +jit)。
典型的应用
List<int>
List<string>
二 范型和使用 obj 的区别, object 装箱拆箱。
装箱的例子。
int val = 100;
object obj = val; //装箱
Console.WriteLine ("对象的值 = {0}", obj); //对象的值 = 100
拆箱的例子。
int val = 100;
object obj = val;
int num = (int) obj; //拆箱。
Console.WriteLine ("num: {0}", num); //num: 100
内部操作。 int,string 类型 内存分配的是栈, 引用类型,使用堆 (托管堆)
C#中对装箱和拆箱都是隐式的,根本的方法是对代码进行分析,而分析最直接的方式是了解原理结何查看反编译的IL代码。比如:在循环体中可能存在多余的装箱,你可以简单采用提前装箱方式进行优化
三 范型类,接口,委托。 (一个类满足不同的具体类型,做相同的事)
3.1 类,接口,委托的泛型写法。
public class GenericClass<T>
{
public T _t;
}
public interface IGeneric<T>
{
T GetT(T t);
}
public delegate void SayHi<T>(T t); //范型委托
//使用时,需指定具体类型。
3.2 范型约束
范型约束。 设好where 后, 传进来的t 只能是 指定类型的
public class Constraint
...
public static void show<T>(T param) where T : People
{
Console.WriteLine($" id = {param.Id}, name = {param.Name}");
}
//program.cs 中使用。
People p = new People()
{
Id= 110,
Name = "p2"
};
People p2 = new People()
{
Id= 111,
Name = "p2"
};
Constraint.show(p);
Constraint.show(p2);
//注意细节 ,where 不能用sealed 类
3.3 协变。(不用甚解)
起因是一种写法不支持。
明明是同一个东西,但不允许写。
//使用如下方法就可以了。 out (只能做为返回值) 定义接口时,有更宽的适用面,工作中几乎不用到。
IEnumerable<Bird> birdList1 = new List<Bird>();
IEnumerable<Bird> birdList2 = new List<Sparrow>();
3.4 范型缓存。
一个类型会有一个缓存。
public class GenericCache<T>
{
static GenericCache()
{
Console.WriteLine(" this is static GenericCache");
_Typetime = string.Format("{0} _ {1}", typeof(T).FullName, DateTime.Now.ToString());
}
private static string _Typetime = "";
public static void GetCache()
{
Console.WriteLine($"GetCache{_Typetime}");
// return _Typetime;
}
Console.WriteLine("*******generic cache start******************");
GenericCache<int>.GetCache();
GenericCache<string>.GetCache();
GenericCache<int>.GetCache();
Console.WriteLine("*******generic end******************");
第二次
GenericCache<int> 时构造函数就没有跑