泛型

    技术2022-05-11  16

    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#泛型 

    最新回复(0)