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

 
约束 说明

T:结构

类型参数必须是值类型。可以指定除 Nullable 以外的任何值类型。有关更多信息,请参见使用可空类型(C# 编程指南)。

T:类

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

T:new()

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

T:<基类名>

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

T:<接口名称>

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

T:U

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

 使用约束的原因

如果要检查泛型列表中的某个项以确定它是否有效,或者将它与其他某个项进行比较,则编译器必须在一定程度上保证它需要调用的运算符或方法将受到客户端代码可能指定的任何类型参数的支持。这种保证是通过对泛型类定义应用一个或多个约束获得的。例如,基类约束告诉编译器:仅此类型的对象或从此类型派生的对象才可用作类型参数。一旦编译器有了这个保证,它就能够允许在泛型类中调用该类型的方法。约束是使用上下文关键字 where 应用的。

[转]

泛型约束基本上有五种:

  • 值类型约束:要求泛型参数必须是值类型,例如int,short以及自定义的stuct等

public class MyClass2<T> 
        where T : struct//这个泛型类只接受值类型的泛型参数 
    { 
    }

  • 引用类型约束:要求泛型参数必须是引用类型,例如string,object,以及自定义的class

public class MyClass<T> 
        where T:class//这个泛型类只接受引用类型的泛型参数 
    { 
    }

  • 构造函数约束:要求泛型参数必须有构造函数

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

  • 接口约束:要求泛型参数必须实现某个接口

public class MyClass4<T> 
        where T : System.IComparable 
    { 
    }

  • 基类约束:要求泛型参数必须继承某个基类

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

实战代码:

using System;
using System.Collections.Generic;
using System.Text;
using System.Data.Common;
using Dare.Utilities.Data;
using Dare.DN.Components;
using System.Data;
using log4net.Core;

namespace Dare.DN.Data
{
    public abstract class DataProviderTemplate<Entity, Key> : DataProviderBase
        where Entity : class, IEntity, IEntity<Key>,new()
        where Key : struct

    {
       
        protected List<EntityRelationDataProvider<Entity, Key>> relationDataProviders;

public DataProviderTemplate()
        {
            relationDataProviders = new List<EntityRelationDataProvider<Entity, Key>>();
        }

#region 关系操作方法
        public void AddRelationDataProviders(params EntityRelationDataProvider<Entity, Key>[] providers)
        {
            relationDataProviders.AddRange(providers);
        }

protected virtual void InsertRelations(TransactionManager manager, DbCommand cmd, IEnumerable<Entity> entities)
        {
            if (entities == null) return;
            foreach (EntityRelationDataProvider<Entity, Key> provider in relationDataProviders)
            {
                provider.Insert(manager, cmd, entities);
            }
        }

protected virtual void InsertRelations(TransactionManager manager, DbCommand cmd, params Entity[] entities)
        {
            InsertRelations(manager, cmd, (IEnumerable<Entity>)entities);
        }

protected virtual void UpdateRelations(TransactionManager manager, DbCommand cmd, IEnumerable<Entity> entities)
        {
            if (entities == null) return;
            foreach (EntityRelationDataProvider<Entity, Key> provider in relationDataProviders)
            {
                provider.Update(manager, cmd, entities);
            }
        }

protected virtual void UpdateRelations(TransactionManager manager, DbCommand cmd, params Entity[] entities)
        {
            UpdateRelations(manager, cmd, (IEnumerable<Entity>)entities);
        }

protected virtual void DeleteRelations(TransactionManager manager, DbCommand cmd, IEnumerable<Key> keys)
        {
            if (keys == null) return;
            foreach (EntityRelationDataProvider<Entity, Key> provider in relationDataProviders)
            {
                provider.Delete(manager, cmd, keys);
            }
        }

protected virtual void DeleteRelations(TransactionManager manager, DbCommand cmd, params Key[] keys)
        {
            DeleteRelations(manager, cmd, (IEnumerable<Key>)keys);
        }

protected virtual void DeleteRelations(TransactionManager manager, DbCommand cmd, string whereClause)
        {
            string whereCluase = ProcessWhereClause(whereClause);
            foreach (EntityRelationDataProvider<Entity, Key> provider in relationDataProviders)
            {
                provider.Delete(manager, cmd, whereClause);
            }
        }

protected virtual void CleanRelations(DbCommand cmd)
        {
            foreach (EntityRelationDataProvider<Entity, Key> provider in relationDataProviders)
            {
                provider.Clean(cmd);
            }
        }

protected virtual void RetrieveRelations(TransactionManager manager, DbCommand cmd, IEnumerable<Entity> entities)
        {
            if (entities == null) return;
            foreach (EntityRelationDataProvider<Entity, Key> provider in relationDataProviders)
            {
                provider.Retrieve(manager, cmd, entities);
            }
        }

protected virtual void RetrieveRelations(TransactionManager manager, DbCommand cmd, params Entity[] entities)
        {
            RetrieveRelations(manager, cmd, (IEnumerable<Entity>)entities);
        }
        #endregion

#region 基本操作方法
        public abstract void Insert(TransactionManager manager, Entity entity);

public abstract void Import(TransactionManager manager, IEnumerable<Entity> entities);

public abstract void Update(TransactionManager manager, Entity entity);

public abstract void Delete(TransactionManager manager, Key key);

public abstract void DeleteAll(TransactionManager manager, string whereClause);

public abstract Entity Get(TransactionManager manager, Key key);

public virtual List<Entity> GetAll(TransactionManager manager, string whereClause, string orderBy)
        {
            return GetPaged(manager, whereClause, orderBy, -1, -1);
        }

public abstract List<Entity> GetPaged(TransactionManager manager, string whereClause, string orderBy, int pageIndex, int pageSize);

public abstract int GetCount(TransactionManager manager, string whereClause);

public abstract long GetVersion(TransactionManager manager, string whereClause);

public abstract Entity Fill(IDataReader reader, Entity entity);
        #endregion

#region 内部操作模板方法
        protected virtual int InternalExecuteNonQuery(TransactionManager manager, string sql, params DbParameter[] parameters)
        {
            int result = 0;
            Execute(manager, delegate(TransactionManager mgr, DbCommand cmd)
            {
                /*------------------------------数据库SQL操作开始----------------------------------*/
                //获取SQL语句
                cmd.CommandText = sql;
                cmd.Parameters.AddRange(parameters);

//执行
                result = cmd.ExecuteNonQuery();
               
                /*------------------------------数据库SQL操作结束----------------------------------*/
            });

return result;
        }

protected virtual List<Entity> InternalGetList(TransactionManager manager, string sql, params DbParameter[] parameters)
        {
            List<Entity> list = new List<Entity>();
            Execute(manager, delegate(TransactionManager mgr, DbCommand cmd)
            {
                /*------------------------------数据库SQL操作开始----------------------------------*/
                //获取SQL语句
                cmd.CommandText = sql;
                cmd.Parameters.AddRange(parameters);

//执行获取实体集
                using (IDataReader reader = cmd.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        list.Add(Fill(reader, null));
                    }
                }

//获取关系对象
                RetrieveRelations(mgr, cmd, list);

/*------------------------------数据库SQL操作结束----------------------------------*/
            });

return list;
        }

protected virtual List<Key> InternalGetKeyList(TransactionManager manager, string sql, params DbParameter[] parameters)
        {
            List<Key> list = new List<Key>();
            Execute(manager, delegate(TransactionManager mgr, DbCommand cmd)
            {
                /*------------------------------数据库SQL操作开始----------------------------------*/
                //获取SQL语句
                cmd.CommandText = sql;
                cmd.Parameters.AddRange(parameters);

//执行获取实体集
                using (IDataReader reader = cmd.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        list.Add((Key)Convert.ChangeType(reader.GetValue(0), typeof(Key)));
                    }
                }

/*------------------------------数据库SQL操作结束----------------------------------*/
            });

return list;
        }

protected virtual T InternalGetValue<T>(TransactionManager manager, string sql, T defaultValue, params DbParameter[] parameters)
        {
            T val = default(T);
            Execute(manager, delegate(TransactionManager mgr, DbCommand cmd)
            {
                /*------------------------------数据库SQL操作开始----------------------------------*/
                //获取SQL语句
                cmd.CommandText = sql;
                cmd.Parameters.AddRange(parameters);

//执行获取实体集
                object objValue = cmd.ExecuteScalar();
                val = DbConvert.ChangeType<T>(objValue, defaultValue);

/*------------------------------数据库SQL操作结束----------------------------------*/
            });

return val;
        }

protected virtual List<T> InternalGetValueList<T>(TransactionManager manager, string sql, T defaultValue, params DbParameter[] parameters)
        {
            List<T> list = new List<T>();
            Execute(manager, delegate(TransactionManager mgr, DbCommand cmd)
            {
                /*------------------------------数据库SQL操作开始----------------------------------*/
                //获取SQL语句
                cmd.CommandText = sql;
                cmd.Parameters.AddRange(parameters);

//执行获取实体集
                using (IDataReader reader = cmd.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        list.Add(DbConvert.ChangeType<T>(reader[0], defaultValue));
                    }
                }

/*------------------------------数据库SQL操作结束----------------------------------*/
            });

return list;
        }

public delegate T FillEntityHandler<T>(IDataReader reader, T entity);
        public delegate void AfterRetrievedEntityListHandler<T>(TransactionManager mgr, DbCommand cmd, IEnumerable<T> entities);

protected T InternalGet<T>(TransactionManager manager, string sqlGet, FillEntityHandler<T> fillEntityHandler, AfterRetrievedEntityListHandler<T> afterRetrieveHandler, params DbParameter[] parameters)
            where T : class
        {
            if (fillEntityHandler == null) throw new ArgumentNullException("fillEntityHandler", "实体数据填充调用方法不能为空!");
            T entity = null;
            Execute(manager, delegate(TransactionManager mgr, DbCommand cmd)
            {
                /*------------------------------数据库SQL操作开始----------------------------------*/
                //获取SQL语句
                cmd.CommandText = sqlGet;
                cmd.Parameters.AddRange(parameters);

//执行获取实体
                using (IDataReader reader = cmd.ExecuteReader())
                {
                    if (reader.Read())
                    {
                        entity = fillEntityHandler(reader, null);
                    }
                }

if (afterRetrieveHandler != null && entity != null)
                {
                    afterRetrieveHandler(mgr, cmd, new T[] { entity });
                }
                /*------------------------------数据库SQL操作结束----------------------------------*/
            });

return entity;
        }

protected Entity InternalGet(TransactionManager manager, string sqlGet, params DbParameter[] parameters)
        {
            return InternalGet<Entity>(manager, sqlGet, Fill, RetrieveRelations, parameters);
        }

protected List<Entity> InternalGetPaged(TransactionManager manager, string sqlGetPaged, string sqlGetCount, int pageIndex, int pageSize, out int totalCount, params DbParameter[] parameters)
        {
            return InternalGetPaged<Entity>(manager, sqlGetPaged, sqlGetCount, Fill, RetrieveRelations, pageIndex, pageSize, out totalCount, parameters);
        }

protected List<T> InternalGetPaged<T>(TransactionManager manager, string sqlGetPaged, string sqlGetCount, FillEntityHandler<T> fillEntityHandler, AfterRetrievedEntityListHandler<T> afterRetrieveHandler, int pageIndex, int pageSize, out int totalCount, params DbParameter[] parameters)
            where T:class
        {
            if (fillEntityHandler == null) throw new ArgumentNullException("fillEntityHandler", "实体数据填充调用方法不能为空!");
            List<T> list = null;
            int count = 0;
            Execute(manager, delegate(TransactionManager mgr, DbCommand cmd)
            {
                /*------------------------------数据库SQL操作开始----------------------------------*/
                //获取总记录数
                cmd.CommandText = sqlGetCount;
                cmd.Parameters.AddRange(parameters);
                count = Convert.ToInt32(cmd.ExecuteScalar());

if (count > 0)
                {
                    //确定分页和获取记录的数量
                    if (pageIndex < 0 || pageSize <= 0)
                    {
                        list = new List<T>(count); //不用分页
                    }
                    else if (count > (pageIndex-1) * pageSize)
                    {
                        list = new List<T>(pageSize);  //使用分页
                    }
                    else
                    {
                        list = new List<T>(0); //分页超过记录数量,输出空记录集
                        return;
                    }

//获取记录集
                    cmd.CommandText = sqlGetPaged;
                    using (IDataReader reader = cmd.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            list.Add(fillEntityHandler(reader, null));
                        }
                    }

if (afterRetrieveHandler != null)
                    {
                        afterRetrieveHandler(mgr, cmd, list);
                    }
                }
                else
                {
                    list = new List<T>(0); //无记录返回空记录集
                    return;
                }
                /*------------------------------数据库SQL操作结束----------------------------------*/
            });

totalCount = count;
            return list;
        }
        #endregion
    }
}

相关资料:

c# 泛型<T>类型参数T的约束where的更多相关文章

  1. C#的泛型的类型参数可以有带参数的构造函数的约束方式吗?

    Review后看到标题让我十分羞愧自己语文功底太差,估计...请见谅......我还特地把这句写回开头了...... 问题 前天遇到的一个问题,所以在MSDN发了个问,刚也丰富了下问题,关于泛型的. ...

  2. 已经为类型参数“Chart”指定了 constraint 子句。必须在单个 where 子句中指定类型参数的所有约束

    public abstract class FillWorkBook<TModel, Chart> where TModel : struct where Chart : new() wh ...

  3. C#泛型对类型参数的推断

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  4. C# 语法特性 - 泛型(C#2.0)

    泛型将 类型参数 的概念引入了 .NET Framework. 泛型主要有两个优点: 1.编译时可以保证类型安全. 2.不用做类型转换,获得一定的性能提升. 泛型方法.泛型委托.泛型接口 除了泛型类之 ...

  5. ASP.NET MVC 企业级实战

    1.泛型 public class List<T>{ } 当定义泛型类的实例时,必须指定这个实例所存储的实际类型,泛型允许程序员将一个实际的数据类型规约延迟至泛型的实例被创建时才确定,泛型 ...

  6. (转).net面试题(老赵)

    转自:http://www.cnblogs.com/chenxiaoran/archive/2012/05/27/2519988.html 1.什么是CLR 公共语言运行时(Comman langua ...

  7. C# 各版本新特性

    C# 2.0 泛型(Generics) 泛型是CLR 2.0中引入的最重要的新特性,使得可以在类.方法中对使用的类型进行参数化. 例如,这里定义了一个泛型类: class MyCollection&l ...

  8. C# 语言历史版本特性(C# 1.0到C# 7.1汇总更新) C#各版本新特性 C#版本和.NET版本以及VS版本的对应关系

    C# 语言历史版本特性(C# 1.0到C# 7.1汇总更新) 2017年08月06日 11:53:13 阅读数:6705 历史版本 C#作为微软2000年以后.NET平台开发的当家语言,发展至今具有1 ...

  9. C# 2.0新加特性

    泛型(Generics) 泛型是CLR 2.0中引入的最重要的新特性,使得可以在类.方法中对使用的类型进行参数化. 例如,这里定义了一个泛型类: class MyCollection<T> ...

随机推荐

  1. 【MySql】数据库连接异常:Thelastpacketsentsuccessfullytotheserverwas0millisecondsago

    参考链接:http://blog.sina.com.cn/s/blog_7540bf5f0102xjpk.html 最近新入职,用了新版的mysql8数据库,结果连接数据库时出现了问题,报了几个异常, ...

  2. Linux文件夹被杀死求解?

    Linux中提示cheese.e-calendar-factory 两个文件夹被杀死 程序错误1.cheese process /usr/bin/cheese was killed by signal ...

  3. PHP0011:学生信息管理案例

    PHP中 html js 混合用

  4. 42.Pycharm连接数据库出现错误:1045、1044:django.db.utils.OperationalError: (1045, "Access denied for user 'Whois'@'localhost' (using password: YES)”)

    1.在pycharm中设置好数据库的连接信息,连接数据库db01, DATABASES = { 'default': { # 指定所使用的的数据库引擎 'ENGINE': 'django.db.bac ...

  5. 使用VS中自带的一键打包功能将我们的ASP.NET Core类库打包并将程序包(类库)发布到NuGet平台上进行管理

    本章将和大家简单分享下如何使用VS中自带的一键打包功能将我们的ASP.NET Core类库打包并将程序包(类库)发布到NuGet平台上进行管理. 一.注册并登录NuGet平台 NuGet官网:http ...

  6. javaweb简单的学生信息录入系统

    讲一下思路,主界面的设计就是用html表单元素,百度查找各个元素的用法,按照自己的想法摆放即可,表单提交后会把数据交给serverlet去处理,在那里定义几个字符串变量来储存获取到的数据,然后按照项目 ...

  7. springMVC请求访问的整个过程

    //以上个随笔(springMVC项目配置文件)为基础,详述springMVC请求的整个过程流向 web.xml                                            ...

  8. CF1254E Send Tree to Charlie

    题意 讲不太清楚,看英文吧 cf 做法 在正式开始之前,我们先来玩一玩性质 首先考虑全\(0\)的情况,即本质不同的方案数 性质1:方案数并不为(n-1)!,即方案与结果不为双射 考虑一条边将树分为两 ...

  9. 【你不知道的javaScript 上卷 笔记7】javaScript中对象的[[Prototype]]机制

    [[Prototype]]机制 [[Prototype]]是对象内部的隐试属性,指向一个内部的链接,这个链接的作用是:如果在对象上没有找到需要的属性或者方法引用,引擎就 会继续在 [[Prototyp ...

  10. PHPStorm使用XDebug调试

    (一)php安装xdebug扩展,PHPStorm+XDebug单步调试 (二)PHPStorm配置XDebug (三)PHPStorm使用XDebug调试 (四)PhpStorm+Xdebug配置单 ...