C#泛型与泛型约束

3 篇文章 0 订阅

为什么要使用泛型

考虑一种堆栈类

 class Stack
    {
        public string[] Elements { get; set; }
        public int Current { get; set; }
        public string Pop()
        {
            return Elements[Current];
        }
        public void Push(string element)
        {
        }
    }

上述堆栈类的元素是字符串类型,但实际开发中可能运用到很多不同的类型,甚至是自定义的类型。显然我们不可能为每一个类型新建一个“Stack”类。


简单的泛型应用

泛型类型参数

在C++模板中,使用“T”代表一个模板类型。这种用法同样延续到了C#中。
此外,还可以以T开头选择更加符合语境的词语,例如:
Dictionary<TKey,TValue>。
在泛型类型或泛型方法定义中,使用"T",以“T”为前缀的描述性词语,作为该泛型的类型参数更加符合规范。

泛型在类中

对于上述的Stack类,可以改写为如下形式

 class Stack<TElement>
    {
        public TElement[] Elements { get; set; }
        public int Current { get; set; }
        public TElement Pop()
        {
            return Elements[Current];
        }
        public void Push(string element)
        {
        }
    }
泛型在接口中

泛型在接口中广泛运用,特别是泛型集合类。
在System.Collections.Generic下存在大量泛型接口
在这里插入图片描述

泛型在接口中的简单使用如下:

interface IInterface<T>
    {
        void fun1(T t);
        T fun2();
    }

泛型在方法中

泛型也可以在方法中使用,代表一个使用类型参数声明的方法。
代码示例

public void Swap<T>(ref T lhs,ref T rhs)
        {
            
        }

泛型约束

定义泛型时,可以对泛型类或泛型接口,方法能够接收的类型参数的种类加以限制。在编译阶段,如果使用不符合要求的类作为类型参数,则会产生编译错误。

泛型约束的声明格式
使用where关键字指定泛型约束

泛型约束使用where关键字指定。例如,要限制一个泛型类必须具有无参数公共构造函数,代码如下:

class Stack<TElement> where TElement :new()
六种约束的格式说明

where T:struct

class Stack<TElement> where TElement :struct

限制类型参数必须是值类型,并且不可以是可空值类型(例如int?,char?,double?,bool?等)
where T: class

class Stack<TElement> where TElement :class

限制类型参数必须是引用类型
where T:基类名

class Stack<TElement> where TElement :BaseClass

限制类型参数必须是继承自指定的基类,或是基类本身
where T:接口名

class Stack<TElement> where TElement :IInterface

限制类型参数必须是实现指定接口,或是指定接口
where T:new()

class Stack<TElement> where TElement :new()

限制类型参数必须具有无参构造函数

泛型约束的意义

泛型约束可以保证传递的类型参数符合一定的条件,并且在编译阶段就可以进行验证:例如添加T: new()约束可以保证传递的类型参数一定包含无参构造函数,添加基类约束可以保证类型一定派生自某个基类。
有了上面的保证,我们就可以在泛型类中调用T类型的构造函数,或者调用其基类的方法。
例如:

为Stack类添加约束
(注意构造器约束需要放在最后)

 public class Stack<TElement> where TElement :Paper,new()
{
        public TElement[] Elements { get; set; }
        public int Current { get; set; }
        public Paper Pop()
        {
            TElement element = new TElement();
            element = Elements[Current];
            return element.DrawOutTissue();
        }
        public void Push(string element)
        {
        }
    }
 public class Paper
{
        Paper()
        {
        }
        Paper DrawOutTissue()
        {
            return new Paper();
        }
    }
泛型约束的一些复杂情况
多个约束

对一个泛型参数可以添加多个约束,例如,可以同时为上述”class Stack “ 添加 class,new(),Paper,
但是:

  • 不可能同时添加struct和class约束
  • 不可能添加多个基类约束
  • 约束之间是 and 关系,不能添加or关系的约束
  • 构造器约束必须最后
  • 构造器约束只能指明无参构造器
  • 约束不会继承
多个参数

对于一种表示“键值对”关系的泛型类KeyValue<TKey,TValue>,该类具有两个泛型参数TKey,TValue,要为其都添加约束,代码如下:

public class KeyValue<TKey,TValue> where TKey : new() 
                                                where TValue: Base,new()
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值