1.泛型简介:通过参数化类型来实现在同一份代码上操作多种数据类型。利用“参数化类型”将类型抽象化,从而实现灵活的复用。在.NET类库中处处都可以看到泛型的身影,尤其是数组和集合中,泛型的存在也大大提高了程序员的开发效率。更重要的是,C#的泛型比C++的模板使用更加安全,并且通过避免装箱和拆箱操作来达到性能提升的目的。因此,我们很有必要掌握并善用这个强大的语言特性。 比较类似与C++的模板)。泛型在编译时提供强大的类型检查,减少数据类型之间的显示转换、装箱操作和运行时的类型检查。
泛型的作用:用于处理算法、数据结构的一种编程方法。泛型通常用在集合和在集合上运行的方法中。泛型主要是提高了代码的重用性。
(1).性能:值类型存储在栈上,引用类型存储在堆上。C#类是引用类型,结构是值类型。将值类型转换为引用类型称为装箱。使用泛型可以不用装箱和拆箱。
(2).类型安全(3).二进制代码的重用(4)代码的扩展
2泛型的应用:
2.1.创建泛型类:定义与一般的类比较类似,只是又要使用泛型类型声明,之后可以作为一个字段成员,或者方法的参数类型。
类型参数T :类似一个占位符,表示某种可能的类型。
2.1泛型类的功能:在创建泛型类的时候,还需要其它的C#的关键字。
创建一个泛型的文档管理器
public class DocumentManager {
private readonly Queue DocumentQueue = new Queue();
public void AddDocument(T doc) {
lock (this){
DocumentQueue.Equals(doc);
}
}
public bool IsDocumentAvailable {
get { return DocumentQueue.Count()>0; }
}
}
class Program
{
static void Main(string[] args)
{
}
}
2.1.1默认值
给DocumentManager
public T GetDocument() {
T doc=default (T);
lock (this)
{
DocumentQueue.Equals(doc);
}
return doc;
}
2.1.2约束:如果泛型类需要调用泛型类型中的方法,就必须添加约束。对于DocumentManager
public interface IDocument
{
string Title { get; set; }
string Content { get; set; }
}
public class Document : IDocument
{
public Document()
{
}
public Document(string title, string content)
{
this.Title = title;
this.Content = content;
}
public string Title { get; set; }
public string Content { get; set; }
}
要使用DocumentManager
public void DisplayAllDocuments()
{
foreach (TDocument doc in documentQueue)
{
Console.WriteLine(doc.Title);
}
}
重新定义类DocumentManager
public class DocumentManager
where TDocument : IDocument//约束条件
{
泛型支持几种约束类型,使用泛型约束还可以合并多个约束。
2.1.3继承
泛型类型可以实现泛型接口,也可以派生自一个类,泛型类可以派生自泛型基类;要求是必须重复接口的泛型类型,或者必须指定基类的类型,于是派生类可以是泛型或者非泛型类。
2.1.4静态成员
泛型类的静态成员需要特别关注。泛型类的静态成员只能在类的一个实例中共享。
3.泛型接口:使用泛型可以定义接口,在接口定义的方法可以带泛型参数。
*3.1泛型接口的协变和抗变
3.2泛型接口的协变
如果泛型类型用out关键字标注,泛型接口就是协变。返回类型只能是T。
3.3泛型接口的抗变
如果泛型类型用in关键字标注,泛型接口就是抗变。接口只能把泛型类型T用作其方法的输入。
*4泛型结构
与类相似,结构也可以是泛型的。他们分厂类似于泛型类,只是没有继承特性。
5泛型方法
泛型方法可以在非泛型类中定义。
5.1方法示例:泛型方法累加集合中所有的元素。
public class Account
{
public string Name { get; private set; }
public decimal Balance { get; private set; }
public Account(string name, Decimal balance)
{
this.Name = name;
this.Balance = balance;
}
}
其中应累加余额的所有账户操作都添加到List
var accounts = new List()
{
new Account("Christian", 1500),
new Account("Stephanie", 2200),
new Account("Angela", 1800)
};
累加Account的方法:
public static decimal AccumulateSimple(IEnumerable source)
{
decimal sum = 0;
foreach (Account a in source)
{
sum += a.Balance;
}
return sum;
}
5.2 带约束的泛型方法
public static decimal Accumulate(IEnumerable source)
where TAccount : IAccount
{
decimal sum = 0;
foreach (TAccount a in source)
{
sum += a.Balance;
}
return sum;
}