作者:@哈桑c(CSDN平台)
专栏:全栈开发自学记录
泛型约束就是告知编译器类型参数必须具备的功能。 在没有任何约束的情况下,类型参数可以是任何类型。 编译器只能假定 System.Object 的成员,它是任何 .NET 类型的最终基类。当分配给泛型的类型参数不满足约束的类型时,编译器会报出 Compiler Error CS0452 的错误。在 C# 中允许使用 where 上下文关键字指定约束。
首先以一段简单的实现增加与设置数组元素的程序作为示例,借此讨论泛型类型参数的约束。同时也方便大家直接复制示例代码,然后对本文中提出的约束类型进行功能测试,辅助大家更好的理解。
代码示例
using System;
using System.Collections.Generic;
public class MyGenericList<T>
{
private List<T> myList;
public MyGenericList()
{
myList = new List<T> { };
}
// 增加元素
public void AddElement(T value)
{
myList.Add(value);
}
// 删除元素
public void RemoveElement(int index)
{
myList.RemoveAt(index);
}
// 更改元素
public void ChangeElement(int index, T value)
{
myList[index] = value;
}
// 查找元素
public T GetElement(int index)
{
return myList[index];
}
}
where T : struct 表示类型参数必须是不可为 null 的值类型。
代码示例:
// 值类型约束
public class MyGenericList<T> where T : struct
{
// 类成员...
}
由于所有值类型都具有可访问的无参数构造函数,因此 struct 约束也表示 new() 约束,所以 struct 约束不能与 new() 约束和 unmanaged 约束一起使用。
where T : class 表示类型参数必须是的引用类型。
代码示例:
// 引用类型约束
public class MyGenericList<T> where T : class
{
// 类成员...
}
此约束还应用于任何类、接口、委托或数组类型。 在可为 null 的上下文中,T 必须是不可为 null 的引用类型。
where T : class? 表示类型参数必须是可为 null 或不可为 null 的引用类型。
代码示例:
// 引用类型约束
public class MyGenericList<T> where T : class?
{
// 类成员...
}
此约束还应用于任何类、接口、委托或数组类型。
where T : notnull 表示类型参数必须是不可为 null 的类型。
代码示例:
// 引用类型约束
public class MyGenericList<T> where T : notnull
{
// 类成员...
}
参数可以是不可为 null 的引用类型,也可以是不可为 null 的值类型。
where T : default 表示重写方法或提供显式接口实现时,如果需要指定不受约束的类型参数,此约束可解决歧义。
代码示例:
// 引用类型约束
public class MyGenericList<T> where T : default
{
// 类成员...
}
default 约束表示基方法,但不包含 class 或 struct 约束。点击了解更多 default 约束。
where T : unmanaged 表示类型参数必须是不可为 null 的非托管类型。
代码示例:
// 引用类型约束
public class MyGenericList<T> where T : unmanaged
{
// 类成员...
}
unmanaged 约束也表示 struct 约束,且不能与 struct 约束或 new() 约束结合使用。
where T : new() 表示类型参数必须具有公共无参数构造函数。
代码示例:
// 引用类型约束
public class MyGenericList<T> where T : new()
{
// 类成员...
}
当构造函数约束与其他约束一起使用时,new() 约束必须最后指定。 new() 约束不能与 struct 和 unmanaged 约束结合使用。
where T :<基类名> 表示类型参数必须是指定的基类或派生自指定的基类。
代码示例:
// 引用类型约束
public class MyGenericList<T> where T :<基类名>
{
// 类成员...
}
在可为 null 的上下文中,T 必须是从指定基类派生的不可为 null 的引用类型。
where T :<基类名>? 表示类型参数必须是指定的基类或派生自指定的基类。
代码示例:
// 引用类型约束
public class MyGenericList<T> where T :<基类名>?
{
// 类成员...
}
在可为 null 的上下文中,T 可以是从指定基类派生的可为 null 或不可为 null 的类型。
where T :<接口名称> 表示类型参数必须是指定的接口或实现指定的接口。
代码示例:
// 引用类型约束
public class MyGenericList<T> where T :<接口名称>
{
// 类成员...
}
可指定多个接口约束。 约束接口也可以是泛型。 在的可为 null 的上下文中,T 必须是实现指定接口的不可为 null 的类型。
where T :<接口名称>? 表示类型参数必须是指定的接口或实现指定的接口。
代码示例:
// 引用类型约束
public class MyGenericList<T> where T :<接口名称>?
{
// 类成员...
}
可指定多个接口约束。 约束接口也可以是泛型。 在可为 null 的上下文中,T 可以是可为 null 的引用类型、不可为 null 的引用类型或值类型。 T 不能是可为 null 的值类型。
where T : U 表示为 T 提供的类型参数必须是为 U 提供的参数或派生自为 U 提供的参数。
代码示例:
// 引用类型约束
public class MyGenericList<T> where T : U
{
// 类成员...
}
在可为 null 的上下文中,如果 U 是不可为 null 的引用类型,T 必须是不可为 null 的引用类型。 如果 U 是可为 null 的引用类型,则 T 可以是可为 null 的引用类型,也可以是不可为 null 的引用类型。