泛型定义:
通过参数化类型来实现在同一份代码上操作多种数据类型。利用“参数化类型”将类型抽象化,从而实现灵活的复用。主要用于解决一系列类似的问题。这种机制允许将类名作为参数传递给泛型类型,并生成相应的对象。将泛型(包括类、接口、方法、委托等)看作模板可能更好理解,模板中的变体部分将被作为参数传进来的类名称所代替,从而得到一个新的类型定义。
优点:
通过允许指定泛型类或方法操作的特定类型,泛型功能将类型安全的任务从您转移给了编译器。不需要编写代码来检测数据类型是否正确,因为会在编译时强制使用正确的数据类型。减少了类型强制转换的需要和运行时错误的可能性。
一、和object实现的类有截然不同的区别:
1.他是类型安全的。实例化了int类型的栈,就不能处理string类型的数据,其他数据类型也一样。
2.无需装箱和折箱。这个类在实例化时,按照所传入的数据类型生成本地代码,本地代码数据类型已确定,所以无需装箱和折箱。
3.无需类型转换。
二、泛型委托启用类型安全回调而无需创建多个委托类。例如,Predicate 泛型委托允许创建对特定类型实现您自己的搜索条件的方法,并允许将您的方法与 Array 类型的方法(如 Find、FindLast 和 FindAll)一起使用。
三、在很多情况下,Visual Basic、Visual C++ 和 C# 编译器能够从上下文中确定泛型方法调用使用的类型,极大地简化了使用泛型方法的语法。例如,下面的代码演示调用 BinarySearch 泛型方法以搜索字符串数组的短格式和长格式。在短格式中,编译器从方法变量的类型中推导出正确的类型参数。
实例:int index = Array.BinarySearch(myArray, " test string "); int index = Array.BinarySearch< string>(myArray, " test string ");
public class Stack<T>
{ private T[] m_item;
public T Pop(){...}
public void Push(T item){...}
public Stack(int i)
{
this.m_item = new T[i];
}
}
只是引入了通用数据类型T就可以适用于任何数据类型,并且类型安全的。这个类的调用方法:
//实例化只能保存int类型的类
Stack<int> a = new Stack<int>(100);
a.Push(10);
a.Push("8888"); //这一行编译不通过,因为类a只接收int类型的数据
int x = a.Pop();
//实例化只能保存string类型的类
Stack<string> b = new Stack<string>(100);
b.Push(10); //这一行编译不通过,因为类b只接收string类型的数据
b.Push("8888");
string y = b.Pop();
泛型类中数据类型的约束:
1、所有的派生约束必须放在类的实际派生列表之后
如:public class LinkedList <K,T> :IEnumerable <T> where K:IComparable <K>
{...}
2、一个泛型参数上可以约束多个接口(用逗号分隔)
public class LinkedList <K,T> where K:IComparable <K> ,IConvertible
3、在一个约束中最多只能使用一个基类
4、约束的基类不能是密封类或静态类
5、不能将System.Delegate或System.Array约束为基类
6、可以同时约束一个基类以及一个或多个接口,但是该基类必须首先出现在派生约束列表中。
7、C#允许你将另一个泛型参数指定为约束
public class MyClass <T,U> where T:U
{...}
8、可以自己定义基类或接口进行泛型约束
9、自定义的接口或基类必须与泛型具有一致的可见性
(2)、构造函数约束
如:
class Node <K,T> where T:new()
{
}
注意:
1、可以将构造函数的约束和派生约束结合起来,前提是构造函数的约束出现在约束列表中的最后
(3)、引用/值类型约束
1、可以使用struct约束将泛型参数约束为值类型(如int、bool、enum),或任何自定义结构
2、同样可以使用class约束将泛型参数约束为引用类型
3、不能将引用/值类型约束与基类约束一起使用,因为基类约束涉及到类
4、不能使用结构和默认构造函数约束,因为默认构造函数约束也涉及到类
5、虽然您可以使用类和默认构造函数约束,但是这样做没有任何价值
6、可以将引用/值类型约束与接口约束组合起来,前提是引用/值类型约束出现在约束列表的开头
public ActionResult MapIndex()
{
Book[] bookArray = new Book[2];
Book book1 = new Book(124, ".Net之美");
Book book2 = new Book(45, "C# 3.0揭秘");
bookArray[0] = book1;
bookArray[1] = book2;
SortHelper<Book> sorter = new SortHelper<Book>();
sorter.BubbleSort(bookArray);
foreach (Book b in bookArray)
{
Console.WriteLine("Id:{0}", b.Id);
Console.WriteLine("Title:{0}\n", b.Title);
}
return View();
}
public class Book : IComparable
{
private int id;
private string title;
public Book() { }
public Book(int id, string title) //构造
{
this.id = id;
this.title = title;
}
public int Id
{
get { return id; }
set { id = value; }
}
public string Title
{
get { return title; }
set { title = value; }
}
// CODE:实现IComparable CompareTo接口
public int CompareTo(object obj)
{
Book book2 = (Book)obj;
return this.Id.CompareTo(book2.Id);
}
}
public class SortHelper<T> where T : IComparable //约束T必须是IComparable 或 继承IComparable
{
public void BubbleSort(T[] array)
{
int length = array.Length;
for (int i = 0; i <= length - 2; i++)
{
for (int j = length - 1; j >= 1; j--)
{
// 对两个元素进行交换
if (array[j].CompareTo(array[j - 1]) < 0)
{
T temp = array[j];
array[j] = array[j - 1];
array[j - 1] = temp;
}
}
}
}
}
泛型类继承中:
2、 父类的类型参数没有被实例化,但来源于子类,也就是说父类和子类都是泛型类,并且二者有相同的类型参数;
//如果这样写的话,显然会报找不到类型T,S的错误
public class TestChild : Test< T, S> { }
//正确的写法应该是
public class TestChild : Test< string, int>{ }
public class TestChild< T, S> : Test< T, S> { }
public class TestChild< T, S> : Test< String, int> { }
泛型接口:
泛型接口的类型参数要么已实例化,要么来源于实现类声明的类型参数
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 泛型
{
class 泛型接口
{
public static void Main()
{
PersonManager man = new PersonManager();
Person per = new Person();
man.PrintYourName(per);
Person p1 = new Person();
p1.Name = "p1";
Person p2 = new Person();
p2.Name = "p2";
man.SwapPerson<Person>(ref p1, ref p2);
Console.WriteLine( "P1 is {0} , P2 is {1}" , p1.Name ,p2.Name);
Console.ReadLine();
}
}
//泛型接口
interface IPerson<T>
{
void PrintYourName( T t);
}
class Person
{
public string Name = "aladdin";
}
class PersonManager : IPerson<Person>
{
#region IPerson<Person> 成员
public void PrintYourName( Person t )//实现接口
{
Console.WriteLine( "My Name Is {0}!" , t.Name );
}
#endregion
//交换
public void SwapPerson<T>( ref T p1 , ref T p2)
{
T temp = default(T) ;
temp = p1;
p1 = p2;
p2 = temp;
}
}
}
接口、抽象类继承#region 接口、抽象类继承 64 public interface ISomeInterface6<T> 65 { 66 T SomeMethod(T t); 67 } 68 public abstract class BaseClass6<T> 69 { 70 public abstract T SomeMethod(T t); 71 } 72 public class SubClass6<T> : BaseClass6<T>,ISomeInterface6<T> 73 { 74 public override T SomeMethod(T t) 75 { return default(T); } 76 } 77 #endregion
泛型委托:
using System;
2using System.Collections.Generic;
3using System.Text;
4
5namespace VS2005Demo2
6{
7 泛型委托#region 泛型委托
8 public class MyClass40<T>
9 {
10 public delegate void GenericDelegate(T t);
11 public void SomeMethod(T t)
12 { }
13 }
15 public class MyClassTest40
16 {
17 public void Tests()
18 {
19 MyClass40<int> obj = new MyClass40<int>();
20 MyClass40<int>.GenericDelegate del;
21
22 del = new MyClass40<int>.GenericDelegate(obj.SomeMethod);
23 del(3);
24
25 //委托推理
26 del = obj.SomeMethod;
27
28 }
29 }
30 #endregion
31
32 委托泛型参数#region 委托泛型参数
33 public class MyClass41<T>
34 {
35 public delegate void GenericDelegate<X>(T t, X x);
36 }
37
38 //外部委托
39 public delegate void GenericDelegate<T>(T t);
40
41 public class MyClass42
42 {
43 public void SomeMethod(int number)
44 { }
45 }
46
47 public class MyClassTest42
48 {
49 public void Test()
50 {
51 MyClass42 obj = new MyClass42();
52 GenericDelegate<int> del;
53 //del = new GenericDelegate<int>(obj.SomeMethod);
54
55 del = obj.SomeMethod;
56 del(3);
58 }
59 }
61 #endregion
63 委托泛型参数#region 委托泛型参数
64 public delegate void MyDelegate<T>(T t) where T : IComparable<T>;
65 #endregion
67 事件#region 事件
69 public delegate void GenericEventHandler<S, A>(S sender, A args);
70
71 public class MyPublisher
72 {
73 public event GenericEventHandler<MyPublisher, EventArgs> MyEvent;
74 public void FireEvent()
75 {
76 MyEvent(this, EventArgs.Empty);
77 }
78 }
80 public class MySubscriber<A> //Optional: can be a specific type
81 {
82 public void SomeMethod(MyPublisher sender, A args)
83 { }
84 }
85 public class MyClassTest43
86 {
87 public void Test()
88 {
89 MyPublisher publisher = new MyPublisher();
90 MySubscriber<EventArgs> subscriber = new MySubscriber<EventArgs>();
91 publisher.MyEvent += subscriber.SomeMethod;
92 }
93 }
94 #endregion
95}