默认情况下,泛型类型参数T可以是任意类型;如果我们希望泛型类型参数希望是某个类型或者是实现某个接口,或者继承某个类,又或者是某一个类型比如值类型,这就需要对类型参数T进行约束,泛型类型参数的约束语法格式如下:
......<T1,T2> where T1:XXX where T2:XXX,XXXX
限定类型参数where, 如果泛型类有多个类型参数约束,逐一用where关键字进行约束定义.
一般常用的泛型类型参数约束如下:
-T:struct 类型参数为数值型(Nullable类型除外)
-T:class 类型参数为引用类型:类,接口,委托,数组等
-T:new() 类型参数类含无参构造函数,一般放约束项最后一个
-T:<基类名> 类型参数必须是某一基类或派生自指定的基类
-T:<接口名> 类型参数必须是指定的接口或指定接口的实现
public class MyGeneric<T> where T:struct{}
public class MyGeneric<T> where T:class,IComparable{}
public class MyGene<T1,T2> where T1:class,ICollection where T2 : class, new() { }
下面demo是通过泛型类加上泛型类型参数约束,要求类型参数T必须实现IComparable接口,类内实现了通用类型数组的冒泡排序:.
public class Sorthelper<T> where T:IComparable
{
public void MySort(T[] arr)
{
for (int i = 1; i <= arr.Length - 1; i++)//i-循环次数
for (int j = 0; j <= arr.Length - i - 1; j++)//j循环是一轮轮循环
if (arr[j].CompareTo(arr[j+1]) == 1)//arr[j]是类型参数T的对象,因为T约束项实现了IComparable,所以可以调用Compare方法
{
T tmp;
tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
pu
然后我们在Main()方法中定义了整型数组,调用泛型类的冒泡排序方法,代码如下:
int[] numbers = { 3, 5, 7, 2, 1, 6, 9, 10, 4 };
Sorthelper<int> mycls = new Sorthelper<int>();
Console.WriteLine("排序前:");
foreach (var item in numbers)
Console.Write(item + "\t");
mycls.MySort(numbers);
Console.WriteLine("\n排序后:");
foreach (var item in numbers)
Console.Write(item + "\t");
此时泛型类的类型参数被指定为int,数组元素为int类型,我们查看下int的结构体定义可以发现.Net已经帮我们实现了IComparable接口,所以int元素可以直接用CompareTo方法进行数据比较排序.
执行Main()方法代码, 数组排序结果如下:
以上demo数据元素类型是.Net定义的int32类型,已经默认实现了IComparable接口成员,如果我们自定义类型,比如自定义实例类型Person,数据元素类型为Person对象,要求对Person对象组成的数组进行排序,这时我们就必须写完Person类型后,在类内实现IComparable接口成员Compare方法,否则冒泡麦序方法内无法对元素大小比较,Person类代码如下:
public class Person:IComparable
{
public string Name { get; set; }
public Person (string name) => this.Name = name;
public int CompareTo(object obj) => this.Name.CompareTo((obj as Person).Name);
}
在Main()方法实例化Person对象数组,并按照姓名进行排序,如下:
//数组元素为复杂的自定义类型的排序,一般选择该类型的某一成员进行排序,如某字段.
Person[] people = {
new Person("Tom"),
new Person("Lily"),
new Person("Lucy"),
new Person("David"),
};
Console.WriteLine();
Console.WriteLine("排序前:");
foreach (var item in people)
Console.Write(item.Name + "\t");
new Sorthelper<Person>().MySort(people);
Console.WriteLine("\n排序后:");
foreach (var item in people)
Console.Write(item.Name + "\t");
Console.ReadKey();
执行以上代码,排序后的结果如下:
大家知道,IComparable接口有泛型版本IComparable<T>,如上demo如果将类型参数约束该为IComparable<T>,即public class Sorthelper<T> where T:IComparable<T>.
同样Perosn类实现的接口也改为IComparable<T>,接口实现的方法也同步更新如下:
public class Person:IComparable<Person>
{
public string Name { get; set; }
public Person (string name) => this.Name = name;
//实现IComparable接口
//public int CompareTo(object obj) => this.Name.CompareTo((obj as Person).Name);
//实现IComparable<T>接口
public int CompareTo(Person other)
{
return this.Name.CompareTo(other.Name);
}
}
运行代码对自定义数组元素进行排序,执行结果也是一样的!
泛型的类型参数约束笔记,抛砖引玉,就这么多,后续会继续更新本贴添加新的demo///