【笔记】C# 泛型约束

🗽 作者:@哈桑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];
    }
}

1、值类型约束(: struct)

where T : struct 表示类型参数必须是不可为 null 的值类型。

代码示例:

// 值类型约束
public class MyGenericList<T> where T : struct
{
	// 类成员... 
}

由于所有值类型都具有可访问的无参数构造函数,因此 struct 约束也表示 new() 约束,所以 struct 约束不能与 new() 约束和 unmanaged 约束一起使用。

2、引用类型约束(: class)

where T : class 表示类型参数必须是的引用类型。

代码示例:

// 引用类型约束
public class MyGenericList<T> where T : class
{
	// 类成员... 
}

此约束还应用于任何类、接口、委托或数组类型。 在可为 null 的上下文中,T 必须是不可为 null 的引用类型。

3、可为空引用类型约束(: class?)

where T : class? 表示类型参数必须是可为 null 或不可为 null 的引用类型。

代码示例:

// 引用类型约束
public class MyGenericList<T> where T : class?
{
	// 类成员... 
}

此约束还应用于任何类、接口、委托或数组类型。

4、不可为空约束(: notnull)

where T : notnull 表示类型参数必须是不可为 null 的类型。

代码示例:

// 引用类型约束
public class MyGenericList<T> where T : notnull
{
	// 类成员... 
}

参数可以是不可为 null 的引用类型,也可以是不可为 null 的值类型。

5、基方法约束(: default)

where T : default 表示重写方法或提供显式接口实现时,如果需要指定不受约束的类型参数,此约束可解决歧义。

代码示例:

// 引用类型约束
public class MyGenericList<T> where T : default
{
	// 类成员... 
}

default 约束表示基方法,但不包含 class 或 struct 约束。点击了解更多 default 约束。

6、非托管类型约束(: unmanaged)

where T : unmanaged 表示类型参数必须是不可为 null 的非托管类型。

代码示例:

// 引用类型约束
public class MyGenericList<T> where T : unmanaged
{
	// 类成员... 
}

unmanaged 约束也表示 struct 约束,且不能与 struct 约束或 new() 约束结合使用。

7、构造函数约束(: new())

where T : new() 表示类型参数必须具有公共无参数构造函数。

代码示例:

// 引用类型约束
public class MyGenericList<T> where T : new()
{
	// 类成员... 
}

当构造函数约束与其他约束一起使用时,new() 约束必须最后指定。 new() 约束不能与 struct 和 unmanaged 约束结合使用。

8、基类名约束(: <基类名>)

where T :<基类名> 表示类型参数必须是指定的基类或派生自指定的基类。

代码示例:

// 引用类型约束
public class MyGenericList<T> where T :<基类名>
{
	// 类成员... 
}

在可为 null 的上下文中,T 必须是从指定基类派生的不可为 null 的引用类型。

9、可为空基类名约束(: <基类名>?)

where T :<基类名>? 表示类型参数必须是指定的基类或派生自指定的基类。

代码示例:

// 引用类型约束
public class MyGenericList<T> where T :<基类名>?
{
	// 类成员... 
}

在可为 null 的上下文中,T 可以是从指定基类派生的可为 null 或不可为 null 的类型。

10、接口类型约束(:<接口名称>)

where T :<接口名称> 表示类型参数必须是指定的接口或实现指定的接口。

代码示例:

// 引用类型约束
public class MyGenericList<T> where T :<接口名称>
{
	// 类成员... 
}

可指定多个接口约束。 约束接口也可以是泛型。 在的可为 null 的上下文中,T 必须是实现指定接口的不可为 null 的类型。

11、可为空接口类型约束(:<接口名称>?)

where T :<接口名称>? 表示类型参数必须是指定的接口或实现指定的接口。

代码示例:

// 引用类型约束
public class MyGenericList<T> where T :<接口名称>?
{
	// 类成员... 
}

可指定多个接口约束。 约束接口也可以是泛型。 在可为 null 的上下文中,T 可以是可为 null 的引用类型、不可为 null 的引用类型或值类型。 T 不能是可为 null 的值类型。

12、自定义约束(: U)

where T : U 表示为 T 提供的类型参数必须是为 U 提供的参数或派生自为 U 提供的参数。

代码示例:

// 引用类型约束
public class MyGenericList<T> where T : U
{
	// 类成员... 
}

在可为 null 的上下文中,如果 U 是不可为 null 的引用类型,T 必须是不可为 null 的引用类型。 如果 U 是可为 null 的引用类型,则 T 可以是可为 null 的引用类型,也可以是不可为 null 的引用类型。

  • 7
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哈桑indie

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值