.net泛型约束

2007-10-06 14:08:54|  分类: .net |字号 订阅

所谓泛型,即通过参数化类型来实现在同一份代码上操作多种数据类型。泛型编程是一种编程范式,它利用“参数化类型”将类型抽象化,从而实现更为灵活的复用。

在定义泛型类时,可以对客户端代码能够在实例化类时用于类型参数的类型种类施加限制。如果客户端代码尝试使用某个约束所不允许的类型来实例化类,则会产生编译时错误。这些限制称为约束。约束是使用 where 上下文关键字指定的。

下表列出了五种类型的约束:

约束 说明

T:struct

类型参数必须是值类型。可以指定除 Nullable 以外的任何值类型。

T:class

类型参数必须是引用类型,包括任何类、接口、委托或数组类型。

T:new()

类型参数必须具有无参数的公共构造函数。当与其他约束一起使用时,new() 约束必须最后指定。

T:<基类名>

类型参数必须是指定的基类或派生自指定的基类。

T:<接口名称>

类型参数必须是指定的接口或实现指定的接口。可以指定多个接口约束。约束接口也可以是泛型的。

T:U

为 T 提供的类型参数必须是为 U 提供的参数或派生自为 U 提供的参数。这称为裸类型约束.

---------------------------------------

一.派生约束

1.常见的

public class MyClass5<T> where T :IComparable { }

2.约束放在类的实际派生之后

public class B { }

public class MyClass6<T> : B where T : IComparable { }

3.可以继承一个基类和多个接口,且基类在接口前面

public class B { }

public class MyClass7<T> where T : B, IComparable, ICloneable { }

二.构造函数约束

1.常见的

public class MyClass8<T> where T :  new() { }

2.可以将构造函数约束和派生约束组合起来,前提是构造函数约束出现在约束列表的最后

public class MyClass8<T> where T : IComparable, new() { }

三.值约束

1.常见的

public class MyClass9<T> where T : struct { }

2.与接口约束同时使用,在最前面(不能与基类约束,构造函数约束一起使用)

public class MyClass11<T> where T : struct, IComparable { }

四.引用约束

1.常见的

public class MyClass10<T> where T : class { }

五.多个泛型参数

public class MyClass12<T, U> where T : IComparable  where U : class { }

六.继承和泛型

public class B<T>{ }

1. 在从泛型基类派生时,可以提供类型实参,而不是基类泛型参数

public class SubClass11 : B<int>
    { }

2.如果子类是泛型,而非具体的类型实参,则可以使用子类泛型参数作为泛型基类的指定类型

public class SubClass12<R> : B<R>
    { }

3.在子类重复基类的约束(在使用子类泛型参数时,必须在子类级别重复在基类级别规定的任何约束)
    public class B<T> where T : ISomeInterface { }
    public class SubClass2<T> : B<T> where T : ISomeInterface { }

4.构造函数约束
    public class B<T> where T : new()
    {
        public T SomeMethod()
        {
            return new T();
        }
    }
    public class SubClass3<T> : B<T> where T : new(){ }

七.泛型方法(C#2.0泛型机制支持在"方法声名上包含类型参数",这就是泛型方法)

1.泛型方法既可以包含在泛型类型中,又可以包含在非泛型类型中

public class MyClass5
    {

public void MyMethod<T>(T t){ }
    }

2.泛型方法的声明与调用

public class MyClass5
    {
        public void MyMethod<T>(T t){ }
    }
    public class App5
    {
        public void CallMethod()
        {
            MyClass5 myclass5 = new MyClass5();
            myclass5.MyMethod<int>(3);
        }
    }

3.泛型方法的重载

//第一组重载
 void MyMethod1<T>(T t, int i){ }

void MyMethod1<U>(U u, int i){ }

//第二组重载
 void MyMethod2<T>(int i){ }
 void MyMethod2(int i){ }

//第三组重载,假设有两个泛型参数
 void MyMethod3<T>(T t) where T : A { }
void MyMethod3<T>(T t) where T : B { }

//第四组重载

public class MyClass8<T,U>
    {
        public T MyMothed(T a, U b)
        {
            return a;
        }
        public T MyMothed(U a, T b)
        {
            return b;
        }
        public int MyMothed(int a, int b)
        {
            return a + b;
        }
    }

4.泛型方法的覆写

(1)public class MyBaseClass1
    {
        public virtual void MyMothed<T>(T t) where T : new() { }
    }
    public class MySubClass1:MyBaseClass1
    {
        public override void MyMothed<T>(T t) //不能重复任何约束
        { }
    }

(2)public class MyBaseClass2
    {
        public virtual void MyMothed<T>(T t)
        { }
    }
    public class MySubClass2 : MyBaseClass2
    {
        public override void MyMothed<T>(T t) //重新定义泛型参数T
        { }
    }

八.虚拟方法

public class BaseClass4<T>
    {
        public virtual T SomeMethod()
        {
            return default(T);
        }
    }
    public class SubClass4 : BaseClass4<int> //使用实参继承的时候方法要使用实参的类型
    {
        public override int SomeMethod()
        {
            return 0;
        }
    }

public class SubClass5<T> : BaseClass4<T> //使用泛型继承时,方法也是泛型
    {
        public override T SomeMethod()
        {
            return default(T);
        }
    }

九.编译器只允许将泛型参数隐式强制转换到 Object 或约束指定的类型

class MyClass<T> where T : BaseClass, ISomeInterface
    {
        void SomeMethod(T t)
        {
            ISomeInterface obj1 = t;
            BaseClass obj2 = t;
            object obj3 = t;
        }
    }

变通方法:使用临时的 Object 变量,将泛型参数强制转换到其他任何类型

class MyClass2<T>
    {
        void SomeMethod(T t)
        {
            object temp = t;
            BaseClass obj = (BaseClass)temp;
        }
    }

十.编译器允许您将泛型参数显式强制转换到其他任何接口,但不能将其转换到类

class MyClass1<T>
    {
        void SomeMethod(T t)
        {
            ISomeInterface obj1 = (ISomeInterface)t; 
            //BaseClass obj2 = (BaseClass)t;           //不能通过编译
        }
    }

十一.使用临时的 Object 变量,将泛型参数强制转换到其他任何类型

class MyClass2<T>
    {
        void SomeMethod(T t)
        {
            object temp = t;
            BaseClass obj = (BaseClass)temp;
        }
    }

十二.使用is和as运算符

public class MyClass3<T>
    {
        public void SomeMethod(T t)
        {
            if (t is int) { }
            if (t is LinkedList<int>) { }
            string str = t as string;
            if (str != null) { }
            LinkedList<int> list = t as LinkedList<int>;
            if (list != null) { }
        }
    }

转载于:https://www.cnblogs.com/kk888/archive/2011/09/01/2161647.html

淡谈泛型约束T(转)相关推荐

  1. .NET支持的泛型约束

    .NET支持的类型参数约束有以下五种: where T : struct | T必须是一个结构类型 where T : class T必须是一个类(class)类型 where T : new() | ...

  2. C#高级语法之泛型、泛型约束,类型安全、逆变和协变(思想原理)

    一.为什么使用泛型? 泛型其实就是一个不确定的类型,可以用在类和方法上,泛型在声明期间没有明确的定义类型,编译完成之后会生成一个占位符,只有在调用者调用时,传入指定的类型,才会用确切的类型将占位符替换 ...

  3. 第五节:泛型(泛型类、接口、方法、委托、泛型约束、泛型缓存、逆变和协变)

    一. 泛型诞生的背景 在介绍背景之前,先来看一个案例,要求:分别输出实体model1.model2.model3的id和name值,这三个实体有相同的属性名字id和name. 1 public cla ...

  4. TypeScript泛型约束

    泛型约束 有了泛型之后,一个函数或容器类能处理的类型一下子扩到了无限大,似乎有点失控的感觉.所以这里又产生了一个约束的概念.我们可以声明对类型参数进行约束. 我们还拿上文中的student栗子来说,想 ...

  5. 【整理】C#2.0泛型编程之概述、default()方法、别名指定与泛型约束

    泛型概述 首先我们看一个在泛型出现之前通用的数据结构示例 通用数据结构类 Code public class Stack {     object[] m_Items;     public Stac ...

  6. C# 泛型约束 new() 的底层细节和性能

    注意:本文不会讲泛型如何使用,关于泛型的概念和泛型约束的使用请微软官方参考链接. https://docs.microsoft.com/zh-cn/dotnet/csharp/language-ref ...

  7. 学习TypeScript 之 Pick与泛型约束

    何为Pick? type Pick<T, K extends keyof T> = {[key in K]: T[key] } 就是从一个复合类型中,取出几个想要的类型的组合,例如: // ...

  8. 淡谈自然场景下小样本OCR文字识别

    淡谈自然场景下小样本OCR文字识别 1. 环境准备 实验中使用了centos7.6,intel core i4710,gtx980M(老机器重装) 安装的时候要注意,linux内核版本和实际版本要一致 ...

  9. Ts extends 泛型约束

    extends 泛型约束 我们一般使用extends来继承接口或者类,但是extends还可以用来泛型约束 function getCnames<T extends { name: string ...

最新文章

  1. react发送Ajax中文问号,如何从Javascript/React发送AJAX请求并在pythonrestapi中接收数据...
  2. 一篇文章告诉你:荣耀10 GT为什么叫全能旗舰
  3. 解决Win8下使用net use命令磁盘映射无效的问题
  4. AngularJS+Satellizer+Node.js+MongoDB-Instagram-20
  5. Linux:如何获取打开文件和文件描述符数量
  6. 23行代码AC_2017 蓝桥杯A组 正则问题(解题报告)
  7. 如何在 Asp.Net Core 中对请求进行限流
  8. 数组方法大全ES5+ES6
  9. 初学shell,今天遇到由wget下载到本地的网页源代码的乱码问题,无聊的写了一个转码的脚本...
  10. HTML+CSS 轮播图 电商网站注册界面 抽屉主页头部界面
  11. unity 中画布随相机视野实时变化
  12. 认知无线电切换算法,基于排队论源码
  13. IDE、SATA、SCSI、SAS、FC、SSD 硬盘类型
  14. DCMTK实现Dicom CT图片读取CT值图像
  15. linux安装完mysql没有服务_Linux中安装mysql之后 mysql服务不能启动
  16. 计算机卸载一个程序正确操作,电脑卸载程序时提示请等待当前程序完成卸载或更改怎么办...
  17. 大二数据库实验报告答案
  18. vue2或者vue3图片上传功能(upload)
  19. C/C++中的atan和atan2函数
  20. 快速校验非法字符工具

热门文章

  1. 看似简单的问题 静态方法和实例化方法的区别
  2. 1月4日链接篇:ASP.NET, ASP.NET AJAX, ASP.NET MVC, Visual Studio, IIS7
  3. [20190401]跟踪dbms_lock.sleep调用.txt
  4. wireshark从入门到精通(协议排错安全篇)4
  5. ActiveMQ简单使用介绍
  6. pl/sql command window 初步接触
  7. AndroidStudio 生成Jar并混淆
  8. 理解class.forName()(good--字节码层面)
  9. Windows下 MySQL命令 常用操作
  10. LWIP再探----内存池管理