C#泛型:(C# Generics)
(广泛的类型)
通过泛型可以定义类型安全类,而不会损害类型安全,性能或工作效率
例:
public class Stack<T>
{
T[] m_Items;
public void Push(T item)
{
...
}
public T Pop()
{
...
}
}
使用:
C#语法:
Stack<int> stack=new Stack<int>();
stack.Push(1);
stack.Push(2);
int number=stack.Pop();
VB语法:
Dim stack As Stack(Of Integer)
stack=new Stack(Of Integer)
stack.Push(3)
Dim number As Integer
number=stack.Pop();
可以使用任何类型来声明和实例化
声明和实例化时都必须用一个特定的类型来代替
一般类型T
泛型是如何实现的:
在.Net2.0中,泛型在IL(中间语言)和CLR本身中
具有本机支持
编译泛型类时,就像编译其他类一样,泛型仅保留一个占位符
而用特定类型实例化泛型代码,编译时会将
泛型替换为实例化的特定类型.
泛型的好处:
一次性地开发,测试和部署代码
通过任何类型(包括将来的类型)来重用它:
编译器支持和类型安全
不会强行对值类型进行装箱和取消装箱
或者对引用类型进行向下强制类型转换
所以性能得到显著提高
在结构中使用泛型:
public struct Point<T>
{
public T x;
public T y;
}
Point<int> point;
point.x=1;
poing.y=2;
Point<double> point;
point.x=1.2;
poing.y=3.4;
default关键字:
假设您不希望在堆棧为空时引
发异常,而是希望返回堆栈中存储
的类型的默认值
值类型返回0
引用类型返回null
public T Pop()
{
m_StackPointer--;
if(m_StackPointer >= 0)
{
return m_Items[m_StackPointer];
}
else
{
m_StackPointer = 0;
throw new InvalidOperationException(
"Cannot pop an empty stack");
}
}
public T Pop()
{
m_StackPointer--;
if(m_StackPointer >= 0)
{
return m_Items[m_StackPointer];
}
else
{
m_StackPointer = 0;
return default(T);
}
}
单个类型可以定义多个泛型
class Node<K,T>
{
public K Key;
public T Item;
public Node<K,T> NextNode;
public Node()
{
Key = default(K);
Item = defualt(T);
NextNode = null;
}
public Node(K key,T item,Node<K,T> nextNode)
{
Key = key;
Item = item;
NextNode = nextNode;
}
}
public class LinkedList<K,T>
{
Node<K,T> m_Head;
public LinkedList()
{
m_Head = new Node<K,T>();
}
public void AddHead(K key,T item)
{
Node<K,T> newNode = new Node<K,T>
(key,item,m_Head.NextNode);
m_Head.NextNode = newNode;
}
}
泛型别名:
在文件头部使用using为特定类型取别名:
别名作用范围是整个文件
using List=LinkedList<int,string>;
class ListClient
{
static void Main(string[] args)
{
List list=new List();
list.AddHead(123,"AAA");
}
}
泛型约束:
public class LinkedList<K,T>
{
T Find(K key)
{
Node<K,T> current = m_Head;
while(current.NextNode != null)
{
if(current.Key == key) //Will not compile
//因为编译器不知道K(实例化
//的实际类型)是否支持==运算
//符.例如默认情况下,结构
//不提供这样的实现
break;
else
current = current.NextNode;
}
return current.Item;
}
public T this[K key]
{
get{return Find(key);}
}
}
LinkedList<int,string> list = new
LinkedList<int,string>();
list.AddHead(123,"AAA");
list.AddHead(456,"BBB");
string item = list[456];
Debug.Assert(item == "BBB");
T Find(K key)
{
Node<K,T> current = m_Head;
while(current.NextNode != null)
{
if(current.Key == key) //Will not compile
break;
else
current = current.NextNode;
}
return current.Item;
}
泛型约束有三种
<1>:派生约束:
用1:Where关键字 2:K:IComparable表示K只接受实现IComparable接口的类型,
尽管如此,还是无法避免传入值类型的K所带来的装箱问题.
System.Collections.Generic命名空间定义了泛型接口IComparable<T>:
public interface IComparable<T>
{
int CompareTo(T other);
bool Equals(T other);
}
避免装箱问题.
public class LinkedList<K,T>where K:ICompamble
{
T Find(K key)
{
Node<K,T> current = m_Head;
while(current.NextNode != null)
{
if(current.Key.CompareTo(key)==0)
break;
else
current = current.NextNode;
}
return current.Item;
}
public T this[K key]
{
get{return Find(key);}
}
}
C#从一个类继承,实现多个接口
在C#2.0中,所有的派生约束必须放在类的实际派生列表之后,
public class LinkedList<K,T>:IEnumberable<T> where K:IComparable<K>
{...}
通常,只须在需要的级别定义约束,
比如:在Node节点定义IComparable<K>约束
是没有意义的,如果一定要在Node上定义
IComparable<K>约束,则LinkedList上也要
定义此约束
class Node<K,T> where K:IComparable<K>
{...}
public class LinedList<KeyType,DataType> where KeyType:IComparable<KeyType>
{
Node<KeyType,DataType>m_Head;
}
一个泛型参数约束多个接口(彼些用逗号分隔)
public class LinkedList<K,T> where K : IComparable<K>,IConvertible
{...}
在一个约束中最多只能使用一个基类,这是因为C# 不支持实现的多重
继承
约束的基类不能是密封类或静态类,并且由编译器实施这一限制
不能将System.Delegate 或System.Array 约束为基类
可以同时约束一个基类以及一个或多个接口,但是该基类必须首先出
现在派生约束列表中
public class LinkedList<K,T> where K : MyBaseClass, IComparable<K>
{...}
密封类:不能派生
静态类:不能实例化
自定义的接口或基类必须与泛型参数具有
一致的可见性,
正确的可见性:
public class MyBaseClass
{
}
interral class MySubClass<T> where T:MyBaseClass
{
}
不正确的可见性:
public class MyBaseClass
{
}
interral class MySubClass<T> where T:MyBaseClass
{
}
<2>:构造函数的约束:
假设您要在一般类的内部实例化一个新的一般对象。问题在于,C#
编译器不知道客户端将使用的类型实参是否具有匹配的构造函数,因
而它将拒绝编译实例化行。
? 为了解决该问题,C# 允许约束一般类型参数,以使其必须支持公共
默认构造函数。这是使用new() 约束完成的。
class Node<K,T> where T : new()
{
public K Key;
public T Item;
public Node<K,T> NextNode;
public Node()
{
Key = default(K);
Item = new T();
NextNode = null;
}
}C#泛型 用MSN跟我交流
(广泛的类型)
通过泛型可以定义类型安全类,而不会损害类型安全,性能或工作效率
例:
public class Stack<T>
{
T[] m_Items;
public void Push(T item)
{
...
}
public T Pop()
{
...
}
}
使用:
C#语法:
Stack<int> stack=new Stack<int>();
stack.Push(1);
stack.Push(2);
int number=stack.Pop();
VB语法:
Dim stack As Stack(Of Integer)
stack=new Stack(Of Integer)
stack.Push(3)
Dim number As Integer
number=stack.Pop();
可以使用任何类型来声明和实例化
声明和实例化时都必须用一个特定的类型来代替
一般类型T
泛型是如何实现的:
在.Net2.0中,泛型在IL(中间语言)和CLR本身中
具有本机支持
编译泛型类时,就像编译其他类一样,泛型仅保留一个占位符
而用特定类型实例化泛型代码,编译时会将
泛型替换为实例化的特定类型.
泛型的好处:
一次性地开发,测试和部署代码
通过任何类型(包括将来的类型)来重用它:
编译器支持和类型安全
不会强行对值类型进行装箱和取消装箱
或者对引用类型进行向下强制类型转换
所以性能得到显著提高
在结构中使用泛型:
public struct Point<T>
{
public T x;
public T y;
}
Point<int> point;
point.x=1;
poing.y=2;
Point<double> point;
point.x=1.2;
poing.y=3.4;
default关键字:
假设您不希望在堆棧为空时引
发异常,而是希望返回堆栈中存储
的类型的默认值
值类型返回0
引用类型返回null
public T Pop()
{
m_StackPointer--;
if(m_StackPointer >= 0)
{
return m_Items[m_StackPointer];
}
else
{
m_StackPointer = 0;
throw new InvalidOperationException(
"Cannot pop an empty stack");
}
}
public T Pop()
{
m_StackPointer--;
if(m_StackPointer >= 0)
{
return m_Items[m_StackPointer];
}
else
{
m_StackPointer = 0;
return default(T);
}
}
单个类型可以定义多个泛型
class Node<K,T>
{
public K Key;
public T Item;
public Node<K,T> NextNode;
public Node()
{
Key = default(K);
Item = defualt(T);
NextNode = null;
}
public Node(K key,T item,Node<K,T> nextNode)
{
Key = key;
Item = item;
NextNode = nextNode;
}
}
public class LinkedList<K,T>
{
Node<K,T> m_Head;
public LinkedList()
{
m_Head = new Node<K,T>();
}
public void AddHead(K key,T item)
{
Node<K,T> newNode = new Node<K,T>
(key,item,m_Head.NextNode);
m_Head.NextNode = newNode;
}
}
泛型别名:
在文件头部使用using为特定类型取别名:
别名作用范围是整个文件
using List=LinkedList<int,string>;
class ListClient
{
static void Main(string[] args)
{
List list=new List();
list.AddHead(123,"AAA");
}
}
泛型约束:
public class LinkedList<K,T>
{
T Find(K key)
{
Node<K,T> current = m_Head;
while(current.NextNode != null)
{
if(current.Key == key) //Will not compile
//因为编译器不知道K(实例化
//的实际类型)是否支持==运算
//符.例如默认情况下,结构
//不提供这样的实现
break;
else
current = current.NextNode;
}
return current.Item;
}
public T this[K key]
{
get{return Find(key);}
}
}
LinkedList<int,string> list = new
LinkedList<int,string>();
list.AddHead(123,"AAA");
list.AddHead(456,"BBB");
string item = list[456];
Debug.Assert(item == "BBB");
T Find(K key)
{
Node<K,T> current = m_Head;
while(current.NextNode != null)
{
if(current.Key == key) //Will not compile
break;
else
current = current.NextNode;
}
return current.Item;
}
泛型约束有三种
<1>:派生约束:
用1:Where关键字 2:K:IComparable表示K只接受实现IComparable接口的类型,
尽管如此,还是无法避免传入值类型的K所带来的装箱问题.
System.Collections.Generic命名空间定义了泛型接口IComparable<T>:
public interface IComparable<T>
{
int CompareTo(T other);
bool Equals(T other);
}
避免装箱问题.
public class LinkedList<K,T>where K:ICompamble
{
T Find(K key)
{
Node<K,T> current = m_Head;
while(current.NextNode != null)
{
if(current.Key.CompareTo(key)==0)
break;
else
current = current.NextNode;
}
return current.Item;
}
public T this[K key]
{
get{return Find(key);}
}
}
C#从一个类继承,实现多个接口
在C#2.0中,所有的派生约束必须放在类的实际派生列表之后,
public class LinkedList<K,T>:IEnumberable<T> where K:IComparable<K>
{...}
通常,只须在需要的级别定义约束,
比如:在Node节点定义IComparable<K>约束
是没有意义的,如果一定要在Node上定义
IComparable<K>约束,则LinkedList上也要
定义此约束
class Node<K,T> where K:IComparable<K>
{...}
public class LinedList<KeyType,DataType> where KeyType:IComparable<KeyType>
{
Node<KeyType,DataType>m_Head;
}
一个泛型参数约束多个接口(彼些用逗号分隔)
public class LinkedList<K,T> where K : IComparable<K>,IConvertible
{...}
在一个约束中最多只能使用一个基类,这是因为C# 不支持实现的多重
继承
约束的基类不能是密封类或静态类,并且由编译器实施这一限制
不能将System.Delegate 或System.Array 约束为基类
可以同时约束一个基类以及一个或多个接口,但是该基类必须首先出
现在派生约束列表中
public class LinkedList<K,T> where K : MyBaseClass, IComparable<K>
{...}
密封类:不能派生
静态类:不能实例化
自定义的接口或基类必须与泛型参数具有
一致的可见性,
正确的可见性:
public class MyBaseClass
{
}
interral class MySubClass<T> where T:MyBaseClass
{
}
不正确的可见性:
public class MyBaseClass
{
}
interral class MySubClass<T> where T:MyBaseClass
{
}
<2>:构造函数的约束:
假设您要在一般类的内部实例化一个新的一般对象。问题在于,C#
编译器不知道客户端将使用的类型实参是否具有匹配的构造函数,因
而它将拒绝编译实例化行。
? 为了解决该问题,C# 允许约束一般类型参数,以使其必须支持公共
默认构造函数。这是使用new() 约束完成的。
class Node<K,T> where T : new()
{
public K Key;
public T Item;
public Node<K,T> NextNode;
public Node()
{
Key = default(K);
Item = new T();
NextNode = null;
}
}C#泛型 用MSN跟我交流