泛型学习(二)
3.1 多参数泛型
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApp { class MoreGenericSample { public static void Main() { czrelation<int, double> sinTable = new czrelation<int, double>(180); for (int i = 0; i < 180; i++) { sinTable.Left[i] = i; sinTable.Right[i] = Math.Sin(Math.PI * i / 180); } //求正弦函数 Console.WriteLine("请输入度数(0~179之间):"); int x = int.Parse(Console.ReadLine()); double y = sinTable.Right[x]; Console.WriteLine("sin({0}度={1})", x, y); //求反正弦函数 Console.WriteLine("请输入一个实数(0~1之间):"); double r = double.Parse(Console.ReadLine()); int pos; for (pos = 0; pos < sinTable.Length; pos++) { if (Math.Abs(r - sinTable.Right[pos]) < 0.005) break; } if (pos == sinTable.Length) Console.WriteLine("没有找到指定的反正弦值。"); else Console.WriteLine("arcsin({0})={1}度", r, sinTable.Left[pos]); Console.ReadLine(); } } public class czrelation<L, R> //多参数泛型类 { public L[] Left; public R[] Right; public int Length { get { return Left.Length; } } public czrelation(int iLength) { Left = new L[iLength]; Right = new R[iLength]; } public int FindLeft(L left) { for (int i = 0; i < Length; i++) { if (Left[i].Equals(left)) return i; return -1; } return 0; } public int FindRight(R right) { for (int i = 0; i < Length; i++) { if (Right[i].Equals(right)) return i; return -1; } return 0; } } }
3.2 类型参数与标识
关于调用时的歧义 (泛型使用时的类型参数 和 普通方法的参数 相同)
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApp { class Test<S,T> { public static void Add(T t) { Console.WriteLine("T={0}",t); } public static void Add(int i) { Console.WriteLine("i={0}", i); } public static void Add(T t, int i) { Console.WriteLine("T={0},i={1}", t,i); } public static void Add(int i, T t) { Console.WriteLine("i={0},T={1}", i,t); } public static void Add(S s) { Console.WriteLine("S={0}", s); } public static void Add(S s, T t) { Console.WriteLine("S={0},T={1}", s, t); } public static void Add(S s, params T[] ts) { } public static void Add(T t, params S[] ss) { } } class Run { static void Main() { //存在歧义,如果有一个方法的定义中不带类型参数(T),则调用此方法 Test<int, int>.Add(1); //存在歧义,如果两个方法的定义中都包含了类型参数,那么代码不能通过编译! //Test<int,int>.Add(1, 2); //编译错误 //string[] str={"1","2","3"}; //Test<int, string[]>.Add(1,str); //int[] iArr = { 1, 2, 3 }; //Test<int, int[]>.Add(1, iArr); Console.ReadLine(); } } }
4 类型限制
4.1 主要限制
public class GA<T> where T : struct //限制T的目标类型为 值类型
punlic class GB<B> where T : class //限制T的目标类型为 引用类型
T t = null; //合法
public class CzRelation<L,R> where L : struct where R : class //多参数限制
4.2 次要限制
将类型参数的目标类型 限制为 从指定的基类或接口中的相关成员。
public class A {}
public class GB<T> where T : A //基类限制
public class CzAssemble<T> where T : Ioutput //接口限制
如果存在主要限制,那么次要限制就只能是接口限制, 而且关键字struct或class要在次要限制前面
public class CzAssemble<T> where T : struct, IOutput
Array,Delegate,Enum,ValueType 不能作为类型参数的限制基类
用作类型限制的类可以是泛型类, 此时它的所有类型参数都必须在被限制的类型中出现
public class BaseClass<T>{}
public class GenericClass<T> where T : BaseClass<T> {}
public class CzRelationElement<L,R> {}
public class CzRelation<T> where T : CzRelationElement<int,T>{} //合法
public class CzRelation<T> where T : CzRelationElement<S,T>{} //不合法
4.3 构造函数限制
要求其目标类型必须提供一个默认的无参构造函数
public class CzAssemble<T> where T : IOutput ,new()
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApp { class GenericConstraintSample { public static void Main() { CzAssemble<int> asm = new CzAssemble<int>(5); Random rand = new Random(); for (int i = 0; i < asm.Length; i++) asm[i] = rand.Next(100); asm.Output(); Console.WriteLine("----------------------------------"); asm.Sort(); asm.Output(); Console.ReadLine(); } } public interface IOutput { void Output(); } //泛型类:集合CzAssemble public class CzAssemble<T> where T : IComparable { protected T[] m_list; public int Length { get { return m_list.Length; } } public T this[int index] { get { return m_list[index]; } set { m_list[index] = value; } } public CzAssemble(int length) { m_list = new T[length]; } public void Output() { foreach (T t in m_list) { if (t != null) { if (t is IOutput) (t as IOutput).Output(); else Console.WriteLine(t); } } } public void Sort() { T tmp; for (int i = m_list.Length; i > 0; i--) { for (int j = 0; j < i - 1; j++) { if (m_list[j].CompareTo(m_list[j + 1]) > 0) { tmp = m_list[j]; m_list[j] = m_list[j + 1]; m_list[j + 1] = tmp; } } } } } }