1泛型
泛型
带有<>符合的类型,就叫泛型
T:Type
作用:代码重用,提高效率,类型安全
分类:泛型方法,泛型类
特点:
延迟声明:定义的时候就是一个占位符,
泛型方法:
Public T 方法名
{
}
基本使用1
public static T SayHello<T>(T t)
{
return t;
}
int i = SayHello<int>(1);
string ii = SayHello<string>("a");
double db = SayHello<double>(3.14);
Program pro = SayHello<Program>(new Program());
Children children = SayHello<Children>(new Children());
基本使用2
public static void Eat<E>(E e)
{
Console.WriteLine("吃方法");
}
在main里调用这个方法用这两种方式都可以,因为这里方法是将泛型作为参数使用而已,泛型本身可以通过传递进来的参数判断类型的,所以这里使用时候也可以不用指定泛型类型
Eat("张三");
或者
Eat<string>("张三");
但是,如果使用时候指定了泛型类型就要给指定的类型的类型值,否则会报错
使用场景:
//用泛型当作参数使用时,在调用该方法时,可以根据参数推断出类型,也就是可以在使用时不用给类型,直接写参数,如:
public static void Show<T>(T param)
{
Console.WriteLine(param.GetType().Name + " " + param);
}
//当返回值使用,调用这个方法时候再具体给返回值类型
public static T Show<T>()
{
//为什么不能直接返回T,因为值类型可以为null,引用类型不可以为null,而且在这个方法里还不确定具体返回是值类型还是引用类型。
//default关键字,如果返回的是一个为空的引用类型,那就返回null,值类型就返回0,
return default(T);
}
//当局部变量使用,一般都要加约束
public static T Show<T>(int a) where T : struct
{
T t = new T();//值类型都有一个隐式的公共无参数的构造方法
return t;
}
泛型类
泛型类在实例化的时候必须指定泛型的类型,就像list集合那样
//泛型类
public class Person<T>
{
public T Name { get; set; }
}
泛型约束
可以限制泛型传递的类型(设置泛型的类型),给类的多个泛型类型添加泛型约束也是在后面添加where即可,每个泛型类型都是用where分隔
where T:struct :限制T必须是值类型
where T:class :限制T必须是引用类型
where T:new() :限制T必须有一个无参构造函数
where T:具体的类 :类本身和它的子类,约束了泛型的类型为这个类的子类
组合约束:where T:具体的类,new()
比如:要求数泛型必须是某个类的子类,并且这个泛型可以在里面实例化
public static T SayHello<T>(T t) where T : Program, new()
{
return t;
}
Program pro = SayHello<Program>(new Program());
Children children = SayHello<Children>(new Children());
上面用到的Children类是Program的子类
泛型约束配泛型类的基本使用
class Program
{
static void Main(string[] args)
{
//因为设置了泛型约束,所以这里只能给Person类型,或者是继承了Person类型的子类类型
PersonHelper<Person> personHelper = new PersonHelper<Person>(new Person() { Id = 1, UserName = "张三" });
personHelper.GetPerson();
Console.ReadKey();
}
}
public class Person
{
public int Id { get; set; }
public string UserName { get; set; }
}
//让泛型类型T为Person的子类
public class PersonHelper<T> where T : Person
{
private T _t = null;//有泛型约束才可以将泛型为空,否则如果传入的泛型类型为值类型则会报错。
public PersonHelper(T t)//构造方法
{
_t = t;
}
//调用创建泛型实例的方法
public T GetPerson()
{
T t = (T)Activator.CreateInstance(typeof(T));//这里只能使用反射创建泛型T的实例,
//如果使用default(T);的话下面对泛型T的属性赋值会报异常,因为Default(T);也只是给一个null而已,并没有实例化
// T t = new T();//也可以通过给泛型T添加new()约束,这样就可以避免通过反射进行实例化
t.UserName = _t.UserName;
t.Id = _t.Id;
return t;
}
}