泛型的概述
.Net从2.0版本就开始支持泛型,引进泛型是为了能提高类或者方法的通用性,例如
//下面是三个方法体一样,但是参数类型不一样的方法
public void Method1(int a)
{
Console.WriteLine(a);
}
public void Method2(string b)
{
Console.WriteLine(b);
}
public void Method3(bool c)
{
Console.WriteLine(c);
}
在泛型引进前,如果要提高通用性,我们会使用object基类来作为输入参数,即
public void Method(object obj)
{
console.WriteLine(obj);
}
但是object类不是类型安全的,并且在这个过程是会涉及装箱拆箱的步骤,会损失一部分性能,后来就引进的泛型的概念,即
public void Method<T>(T t)
{
console.WriteLine(t);
}
泛型的优点
- 性能好
不需要再通过类型转换,装箱、拆箱,泛型是在使用时再定义类型,不用损耗过多性能 - 类型安全
object拆箱时需要转成装箱时的类型,容易出现错误,泛型是定义类型后就不需要再拆箱。
泛型类
public class DocumentManager<T>
{
private readonly Queue<T> documentQueue = new Queue<T>();
public void AddDocument(T doc)
{
lock (this)
{
documentQueue.Enqueue(doc);
}
}
public bool IsDocumentAvailable
{
get
{
return documentQueue.Count > 0;
}
}
public T GetDocument()
{
//default关键字,将null赋予引用类型,将0赋予值类型;
T doc = default(T);
lock (this)
{
doc = documentQueue.Dequeue();
}
return doc;
}
}
默认值:
GetDocument方法中,doc应该指定为null,但是null只能指定给引用类型,但是万一doc是属于值类型,null就会报错,所以通过default来赋值。
注意:
GetDocument<int> G1 = new GetDocument<int>();
GetDocument<int> G2 = new GetDocument<int>();
当GetDocument<T>中T的类型相同时,他们是同一个类;
当GetDocument<T>中T的类型不相同时,他们不是同一个类;
public class Document<TDocument> where TDocument:IDocument
{
string Title { get; set; }
string Content { get; set; }
public Document()
{
}
public Document(string title,string content)
{
this.Title = title;
this.Content = content;
}
}
public interface IDocument
{
string Title { get; set; }
string Content { get; set; }
}
泛型约束:
泛型接口
协变
public class People
{
public int Id { get; set; }
}
public class Teacher:People
{
public string Name { get; set; }
}
//泛型接口 注意out限制了返回类型只能是T
interface IListOut<out T>
{
T GetT();
}
//泛型类继承泛型接口
public class ListOut<T> : IListOut<T>
{
public T GetT()
{
return default(T);
}
}
//主程序
public class Program
{
static void Main(string[] args)
{
IListOut<People> listOut = new ListOut<People>();
//协变 父类类型装子类list
IListOut<People> listOut1 = new ListOut<Teacher>();
}
}
抗变
//注意In
interface IListOut<in T>
{
void show(T t);
}
public class ListOut<T> : IListOut<T>
{
public void show(T t)
{
}
}
public class People
{
public int Id { get; set; }
}
public class Teacher:People
{
public string Name { get; set; }
}
//主程序
public class Program
{
static void Main(string[] args)
{
IListOut<People> listOut = new ListOut<People>();
//协变 子类类型装父类list
IListOut<Teacher> listOut1 = new ListOut<People>();
}
}