本篇主要讲述C#中泛型的概念,包括泛型类和泛型方法。
- C# 2.0中的Generics概念类似于C++中的template,主要用于克服使用object无法达到的compile-time type-check,同时提供了无需使用cast即可将一套class/method/struct用于多种类型的功能。
- Generic classes/methods使用type作为参数,.NET Framework 2.0在System.Collections.Generic中包含了大量的Generic Collections。
using System.Collections.Generic;
...
Queue<Circle> myQueue = new Queue<Circle>();
Circle myCircle = new Circle();
myQueue.Enqueue(myCircle);
...
myCircle = myQueue.Dequeue();
- Generic Queue class的定义方法是
public class Queue<T> : …//T代表了实际使用的类型
{
...
public void Enqueue( T item );
public T Dequeue();
...
}
- 一个generic class可以具有多个type parameters,例如System.Collecions.Generic.Dictionary就需要两个type参数,一个Key 一个Value。
public class Dictionary<T, U>
{
...
public virtual U this[ T key ] { get; set; }
...
}
Dictionary<string, Person> directory = new Dictionary<string, Person>();
Person john = new Person();
directory["John"] = john;
...
john = directory["John"];
- 你可以规定Generic Class的type参数只能是实现了某些方法的类,
public class PrintableCollection<T> where T : IPrintable
- Class library是一系列存储于assembly中的compiled classes, structs and delegates,通常使用dll后缀,其他项目可以通过添加对这个assembly的引用来使用其中的class。
- 如果你希望可以使用‘>=’等操作符对类进行比较,需要实现IComparable接口,这个接口包含一个CompareTo方法(接受一个Object参数和当前instance比较,返回一个整数作为比较结果,小于0表示当前instance小于参数,等于0表示二者相等,大于0表示当前instance大于参数)
class Circle : System.IComparable
{
...
public int CompareTo(object obj)
{
Circle circObj = (Circle)obj; // cast the parameter to its real type
if (this.Area() == circObj.Area())
return 0;
if (this.Area() > circObj.Area())
return 1;
return -1;
}
}
- 因为System.IComparable接口使用object作为参数,所以不是type-safe的,你可以使用IComparable<T>接口来获得类型的安全性,其包含了下面两个方法。你也可以同时实现着两个interface。
int CompareTo(T other);
bool Equals(T other);
//上面那个例子可以重新实现为:
class Circle : System.IComparable<Circle>
{
...
public int CompareTo(Circle other)
{
if (this.Area() == other.Area())
return 0;
if (this.Area() > other.Area())
return 1;
return -1;
}
public bool Equals(Circle other)
{
return (this.CompareTo(other) == 0);
}
}
- 你可以实现自己的泛型类,例子如下:
public class Tree<T> where T : IComparable<T>
{
...
public Tree(T nodeValue)
{
this.data = nodeValue;
this.left = null;
this.right = null;
}
public Tree<T> LeftTree
{
get { return this.left; }
set { this.left = value; }
}
public void Insert (T newItem)
{
}
...
private T data;
private Tree<T> left;
private Tree<T> right;
}
- 你可以实现一个泛型的method,将其参数、返回值定义为type参数;泛型方法通常和泛型类一起使用,将泛型类作为参数和返回值。
static void Swap<T>( ref T first, ref T second)
{
T temp = first;
first = second;
second = temp;
}
int a = 1, b = 2;
Swap<int>(ref a, ref b);
...
string s1 = "Hello", s2 = "World";
Swap<string>(ref s1, ref s2);
(待续,下一篇将主要描述C#中的操作符重载)