泛型约束实际应用,泛型编制程序之泛型类

前言

所谓泛型,即经过参数化类型来兑今后一如既往份代码上操作各种数据类型。

泛型编程是1种编制程序范式,它应用“参数化类型”将品种抽象化,从而完毕更灵活的复用。在概念泛型类时,在对客户端代码能够在实例化类时,能够用项目参数的连串连串施加限制。在搭建底层框架时,是最广泛的编制程序形式。

 

来自Hauk的文章 C#
泛型编制程序之泛型类、泛型方法、泛型约束

泛型方法

一、List

泛型类

泛型类范例:

namespace ORDER.SYSTEM.DAL.Data
{
    public abstract class AgentBase<T> where T : class, new()
    {

        //私有实例
        private static T _instance;

        // 定义一个标识确保线程同步
        private static readonly object locker = new object();

        /// <summary>
        /// 返回单例对象
        /// </summary>
        /// <returns></returns>
        public static T Instance()
        {
            if (_instance == null)
            {
                lock (locker)
                {
                    if (_instance == null)
                    {
                        switch (typeof(T).FullName)
                        {
                            case "ORDER.SYSTEM.BLL.TextImpl":
                                _instance = new T(); //此处的T表示命名空间的下的某个类被托管或重写,只保留功能
                                break;
                            default:
                                _instance = new T();
                                break;
                        }
                    }
                }
            }
            return _instance;
        }

    }
}

泛型类的指标是为着约束泛型方法传参数类型或回到值类型。

 

  

    在C#二.0中,方法可以定义特定于其实践范围的泛型参数,如下所示:

壹)、表示可经过索引访问的靶子的强类型列表;提供用于对列表进行查找、排序和操作的诀要。
2)、是ArrayList类的泛型等效类。
三)、能够运用三个整数索引访问此聚众中的成分;索引从零 发轫。
肆)、能够接过null空引用(VB中的Nothing)。
5)、允许再次成分

泛型方法

在C# 二.0中,方法能够定义特定于其进行范围的泛型参数,如下所示:

public class MyClass<T>
{
    //指定MyMethod方法用以执行类型为X的参数
    public void MyMethod<X>(X x) 
    {
        //
    }

    //此方法也可不指定方法参数
    public void MyMethod<X>() 
    {
        //
    }
}   

尽管富含类不适用泛型参数,你也得以定义方法特定的泛型参数,如下所示:

public class MyClass
{
    //指定MyMethod方法用以执行类型为X的参数
    public void MyMethod<X>(X x) 
    {
        //
    }

    //此方法也可不指定方法参数
    public void MyMethod<X>() 
    {
        //
    }
}

注意:属性和索引器不可能钦定本人的泛型参数,它们只可以动用所属类中定义的泛型参数进行操作。

在调用泛型方法的时候,你能够提供要在调用场地采取的类型,如下所示:

//调用泛型方法
MyClass myClass = new MyClass();
myClass.MyMethod<int>(3);

 

泛型推理:

在调用泛型方法时,C#编写翻译器丰富聪明,基于传入的参数类型来推测出不错的门类,并且它同意完全省略类型规范,如下所示:

//泛型推理机制调用泛型方法
MyClass myClass = new MyClass();
myClass.MyMethod(3);

专注:泛型方法不可能只根据重回值的连串推测出类型,代码如下:

public GenericMethodDemo()
{        
    MyClass myClass = new MyClass();
    /****************************************************
    无法从用法中推理出方法“GenericMethodDemo.MyClass.MyMethod<T>()”的类型参数。
    请尝试显式指定类型参数。
    ***************************************************/
    int number = myClass.MyMethod();
}

public class MyClass
{
    public T MyMethod<T>() 
    {
        //
    }
}

泛型方法中泛型参数的自律,如下:

public class MyClass
{

    public void MyMethod<X>(X x) where X:IComparable<X>
    {
        //
    }
}

 

  所谓泛型,即透过参数化类型来兑以往同一份代码上操作各类数据类型。

亚洲必赢官网 1

二、List

.NET泛型约束

一经客户端代码尝试选取有些约束所不允许的品种来实例化类,则会时有爆发编写翻译时不当。这个限制称为约束。约束是采取where 上下文关键字内定的。

下表列出了四种档次的牢笼:

 

约束 说明

T:struct

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

T:class

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

T:new()

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

T:<基类名>

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

T:<接口名称>

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

T:U

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

 

 

 

派生约束

1.常见的

public class MyClass5 where T :IComparable { }

二.羁绊放在类的其实派生之后

public class B { }

public class MyClass6 : B where T : IComparable { }

三.能够继续一个基类和多少个接口,且基类在接口前面

public class B { }

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

 

构造函数约束

1.常见的

public class MyClass8 where T : new() { }

二.得以将构造函数约束和派生约束组合起来,前提是构造函数约束出现在封锁列表的末段

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

 

值约束

1.常见的

public class MyClass9 where T : struct { }

2.与接口约束同时选取,在最前方(不可能与基类约束,构造函数约束共同行使)

public class MyClass11 where T : struct, IComparable { }

 

引用约束

常见的

public class MyClass10 where T : class { }

四个泛型参数

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

 

 

PS:欢迎扫描下方二维码,参预QQ群

亚洲必赢官网 2

 

作者:Jacky

来源:

注脚:本文版权归作者和新浪共有,欢迎转发,但未经我同意必须保留此段评释,且在篇章页面明显地点给出最初的作品连接,不然保留追究法律权利的职分。

  泛型编制程序是一种编制程序范式,它选用“参数化类型”将项目抽象化,从而完结更为灵活的复用。在概念泛型类时,在对客户端代码能够在实例化类时,能够用项目参数的档次连串施加限制。

    public class MyClass<T>
    {
        //钦点MyMethod方法用以实施项目为X的参数
        public void MyMethod<X>(X x) 
        {
            //亚洲必赢官网 3
        }

List

泛型方法

在C#
2**.0**中,方法能够定义特定于其实施范围的泛型参数,如下所示:

public class MyClass<T>
{
    //指定MyMethod方法用以执行类型为X的参数
    public void MyMethod<X>(X x) 
    {
        //
    }

    //此方法也可不指定方法参数
    public void MyMethod<X>() 
    {
        //
    }
}   

尽管富含类不适用泛型参数,你也能够定义方法特定的泛型参数,如下所示:

public class MyClass
{
    //指定MyMethod方法用以执行类型为X的参数
    public void MyMethod<X>(X x) 
    {
        //
    }

    //此方法也可不指定方法参数
    public void MyMethod<X>() 
    {
        //
    }
}

注意:属性和**索引器**不可能钦点自个儿的泛型参数,它们只可以动用所属类中定义的泛型参数实行操作。

在调用泛型方法的时候,你能够提供要在调用场地使用的项目,如下所示:

//调用泛型方法
MyClass myClass = new MyClass();
myClass.MyMethod<int>(3);

 

泛型推理:

在调用泛型方法时,C#编写翻译器丰裕聪明,基于传入的参数类型来揆度出不错的花色,并且它同意完全省略类型规范,如下所示:

//泛型推理机制调用泛型方法
MyClass myClass = new MyClass();
myClass.MyMethod(3);

瞩目:泛型方法不可能只依照重返值的项目预计出类型,代码如下:

public GenericMethodDemo()
{        
    MyClass myClass = new MyClass();
    /****************************************************
    无法从用法中推理出方法“GenericMethodDemo.MyClass.MyMethod<T>()”的类型参数。
    请尝试显式指定类型参数。
    ***************************************************/
    int number = myClass.MyMethod();
}

public class MyClass
{
    public T MyMethod<T>() 
    {
        //
    }
}

泛型方法中泛型参数的约束,如下:

public class MyClass
{

    public void MyMethod<X>(X x) where X:IComparable<X>
    {
        //
    }
}

        //此方法也同意内定方法参数
        public void MyMethod<X>() 
        {
            //亚洲必赢官网 4
        }
    }   

List

泛型类

无法为类级别的泛型参数提供方式级其余束缚。类级别泛型参数的保有约束都必须在类作用范围中定义,代码如下所示

public class MyClass<T>
{

    public void MyMethod<X>(X x,T t) where X:IComparable<X> where T:IComparer<T>
    {
        //
    }
}

而上边包车型大巴代码是不利的:

public class MyClass<T> where T:IComparable<T>
{

    public void MyMethod<X>(X x,T t) where X:IComparable<X> 
    {
        //
    }
}

泛型参数虚方法的重写:子类方法必须重新定义该措施特定的泛型参数,代码如下

public class MyBaseClass
{
    public virtual void SomeMethod<T>(T t)
    {
        //
    }
}
public class MyClass :MyBaseClass
{
    public override void SomeMethod<X>(X x)
    {

    }
}

再者子类中的泛型方法无法重复基类泛型方法的牢笼,那或多或少和泛型类中的虚方法重写是有分其余,代码如下

public class MyBaseClass
{
    public virtual void SomeMethod<T>(T t) where T:new()
    {
        //
    }
}
public class MyClass :MyBaseClass
{
    //正确写法
    public override void SomeMethod<X>(X x)
    {

    }

    ////错误 重写和显式接口实现方法的约束是从基方法继承的,因此不能直接指定这些约束
    //public override void SomeMethod<X>(X x) where X:new()
    //{

    //}
}

 

子类方法调用虚拟方法的基类实现:它必须钦赐要代表泛型基础措施类型所接纳的种类实参。你能够自个儿显式的钦赐它,也能够依靠类型推理(若是只怕的话)代码如下:

public class MyBaseClass
{
    public virtual void SomeMethod<T>(T t) where T:new()
    {
        //
    }
}
public class MyClass :MyBaseClass
{
    //正确写法
    public override void SomeMethod<X>(X x)
    {
        base.SomeMethod<X>(x);
        base.SomeMethod(x);
    }
}

 

亚洲必赢官网 5

List

泛型委托

在有些类中定义的信托能够采用该类的泛型参数,代码如下

public class MyClass<T>
{
    public delegate void GenericDelegate(T t);
    public void SomeMethod(T t)
    {

    }
}
public GenericMethodDemo()
{
    MyClass<int> obj = new MyClass<int>();
    MyClass<int>.GenericDelegate del;
    del = new MyClass<int>.GenericDelegate(obj.SomeMethod);
    del(3);
}

 

委托推理:C#贰.0使你能够将艺术引用的向来分配转变为委托变量。将地方的代码改造如下

public class MyClass<T>
{
    public delegate void GenericDelegate(T t);
    public void SomeMethod(T t)
    {

    }
}
public GenericMethodDemo()
{
    MyClass<int> obj = new MyClass<int>();
    MyClass<int>.GenericDelegate del;

    //委托推理
  del = obj.SomeMethod;
    del(3);
 }  

泛型委托的封锁

信托级别的束缚只在宣称委托变量和实例化委托时选择,类似于在项目和措施的成效范围中履行的此外任何自律。

泛型和反光

在Net2.0中间,扩充了反光以支撑泛型参数。类型Type今后得以表示带有一定类型的实参(或绑定类型)或未钦命类型的泛型(或称未绑定类型)。像C#壹.第11中学那么,您能够通过运用typeof运算符或透过调用每一个门类匡助的GetType()来赢得其余类型的Type。代码如下:

LinkedList<int> list = new LinkedList<int>();
 Type type1 = typeof(LinkedList<int>);
 Type type2 = list.GetType();
 Response.Write(type1 == type2);
 typeof和GetType()也可以对泛型参数进行操作,如下

public class MyClass<T>
{
public void SomeMethod(T t)
{
    Type type = typeof(T);
    HttpContext.Current.Response.Write(type==t.GetType());
}
}

typeof还足以对未绑定的泛型举办操作,代码如下

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        Type unboundType = typeof(MyClass<>);
        Response.Write(unboundType.ToString());
    }
}

public class MyClass<T>
{
    public void SomeMethod(T t)
    {
        Type type = typeof(T);
        HttpContext.Current.Response.Write(type==t.GetType());
    }
}

 

请留意”<>”的用法。要对含有七个品种参数的未绑定泛型类进行操作,请在”<>”中使用”,”

Type类中添加了新的格局和质量,用于提供关于该项指标泛型方面的反光新闻,见MSDN。

 

 

    尽管带有类不适用泛型参数,你也能够定义方法特定的泛型参数,如下所示:

三、List

.net泛型约束  

  假如客户端代码尝试使用有个别约束所不容许的门类来实例化类,则会产生编写翻译时不当。这个限制称为约束。约束是行使
where 上下文关键字钦点的。

亚洲必赢官网 6

Capacity
收获或设置该内部数据结构在不调整大小的动静下能够容纳的要素总数。

一、 约束

  下表列出了伍体系型的封锁:

约束 说明

T:struct

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

T:class

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

T:new()

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

T:<基类名>

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

T:<接口名称>

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

T:U

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

 

    public class MyClass
    {
        //内定MyMethod方法用以实施项目为X的参数
        public void MyMethod<X>(X x) 
        {
            //亚洲必赢官网 7
        }

Count
获取 List

 

        //此方法也承认内定方法参数
        public void MyMethod<X>() 
        {
            //亚洲必赢官网 8
        }
    }

四、List

派生约束

1.常见的

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

二.束缚放在类的实在派生之后

public
class B { }

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

三.方可持续多少个基类和四个接口,且基类在接口后面

public
class B { }

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

亚洲必赢官网 9

Add
将对象添加到 List

构造函数约束

1.常见的

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

二.足以将构造函数约束和派生约束组合起来,前提是构造函数约束出现在约束列表的末尾

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

    注意:属性和索引器不能够钦命本身的泛型参数,它们只好选拔所属类中定义的泛型参数实行操作。

AddRange
将点名集合的成分添加到 List

值约束

1.常见的

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

二.与接口约束同时选拔,在最前边(不可能与基类约束,构造函数约束共同利用)

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

    在调用泛型方法的时候,你能够提供要在调用场地选用的档次,如下所示:

AsReadOnly
归来当前集结的只读 IList

引用约束

常见的

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

//调用泛型方法
MyClass myClass = new MyClass();
myClass.MyMethod<int>(3);

BinarySearch(T)
应用暗中认可的相比较器在全体已排序的 List

八个泛型参数

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

 

    泛型推理:在调用泛型方法时,C#编写翻译器丰硕聪明,基于传入的参数类型来揆度出不错的花色,并且它同意完全省略类型规范,如下所示:

BinarySearch(T, IComparer

二、 继承和泛型

public
class B<T>{ }

一.
在从泛型基类派生时,能够提供品类实参,而不是基类泛型参数

   
public class SubClass11 : B<int>
    { }

二.比方子类是泛型,而非具体的档次实参,则足以行使子类泛型参数作为泛型基类的钦点项目

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

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

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

//泛型推理机制调用泛型方法
MyClass myClass = new MyClass();
myClass.MyMethod(3);

BinarySearch(Int32, Int32, T, IComparer

3、泛型方法

(C#泛型约束实际应用,泛型编制程序之泛型类。二.0泛型机制帮忙在”方法声名上含蓄类型参数”,那便是泛型方法)

壹.泛型方法既能够包含在泛型类型中,又足以分包在非泛型类型中

public class MyClass5
    {

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

二.泛型方法的扬言与调用

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;
    }
}

 

四.泛型方法的覆写

(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
        { }
    }

    注意:泛型方法无法只依据再次回到值的档次推测出类型,代码如下:

Clear
从 List

四、虚拟方法

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);
    }
}

 

亚洲必赢官网 10

Contains
规定某成分是还是不是在 List

伍、泛型参数隐式强制转换

编写翻译器只同意将泛型参数隐式强制转换成 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;
    }
}

 

     public GenericMethodDemo()
     {        
        MyClass myClass = new MyClass();
        /****************************************************
        不可能从用法中国对外演出公司绎出艺术“GenericMethod德姆o.MyClass.MyMethod<T>()”的类别参数。
        请尝试显式钦赐项目参数。
        ***************************************************/
        int number = myClass.MyMethod();
     }

ConvertAll

陆、 泛型参数字呈现式强制转换

编写翻译器允许你将泛型参数字呈现式强制转换来别的任何接口,但不可能将其转移到类

 

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

 

 

    public class MyClass
    {
        public T MyMethod<T>() 
        {
            //亚洲必赢官网 11
        }
    }

CopyTo(T[])
将整个 List

七、 泛型参数强制转换成其余任何类型

利用权且的 Object 变量,将泛型参数强制转换成别的任何类型

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

 

亚洲必赢官网 12

Exists
确定 List

八、使用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) { }
    }
}

 

 

    泛型方法中泛型参数的自律,如下:

Find
搜索与钦赐谓词所定义的尺度相相称的成分,并再次回到整个 List

亚洲必赢官网 13

FindIndex(Predicate

    public class MyClass
    {
        
亚洲必赢官网 ,        public void MyMethod<X>(X x) where X:IComparable<X>
        {
            //亚洲必赢官网 14
        }
    }

ForEach
对 List

亚洲必赢官网 15

GetEnumerator
回来循环访问 List

   
您不能为类级别的泛型参数提供方式级别的约束。类级别泛型参数的保有约束都必须在类功用范围中定义,代码如下所示

IndexOf(T)
摸索钦定的靶子,并重临整个 List

亚洲必赢官网 16

Insert
将成分插入 List

    public class MyClass<T>
    {
        
        public void MyMethod<X>(X x,T t) where X:IComparable<X> where T:IComparer<T>
        {
            //亚洲必赢官网 17
        }
    }

InsertRange
将集聚中的某些成分插入 List

亚洲必赢官网 18

LastIndexOf(T)
寻找钦定的靶子,并回到整个 List

而上面包车型客车代码是天经地义的

Remove
从 List

亚洲必赢官网 19

Reverse()
将整个 List

    public class MyClass<T> where T:IComparable<T>
    {
        
        public void MyMethod<X>(X x,T t) where X:IComparable<X> 
        {
            //亚洲必赢官网 20
        }
    }

Sort()
应用默认比较器对总体 List

亚洲必赢官网 21

5、常用方法实例

   
泛型参数虚方法的重写:子类方法必须再度定义该格局特定的泛型参数,代码如下

(一)创设及初叶化:
List

亚洲必赢官网 22

(二)添加一个因素 List.Add(T item)
mlist.Add(“d”);

    public class MyBaseClass
    {
        public virtual void SomeMethod<T>(T t)
        {
            //亚洲必赢官网 23
        }
    }
    public class MyClass :MyBaseClass
    {
        public override void SomeMethod<X>(X x)
        {
            
        }
    }

(3)添加集合成分
string[] Arr2
={“f”,”g”.”h”};mlist.AddRange(Arr2);

亚洲必赢官网 24

(四)在index地方添加一个要素 Insert(int index,T item)
mlist.Insert(1,”p”);

再正是子类中的泛型方法无法重复基类泛型方法的约束,那一点和泛型类中的虚方法重写是有分其余,代码如下

(5)遍历List中元素
foreach(T element in mlist)
T的花色与mlist证明时一样{  Console.WriteLine(element);}

亚洲必赢官网 25

(6)删除成分
List.Remove(T item)
删除八个值mlist.Remove(“a”);

    public class MyBaseClass
    {
        public virtual void SomeMethod<T>(T t) where T:new()
        {
            //亚洲必赢官网 26
        }
    }
    public class MyClass :MyBaseClass
    {
        //正确写法
        public override void SomeMethod<X>(X x)
        {
            
        }

List.RemoveAt(int
index);删除下标为index的成分mlist.RemoveAt(0);List.RemoveRange(int
index,int
count); 下标index开始,删除count个元素mlist.RemoveRange(3,2);

        ////错误 重写和显式接口完毕形式的束缚是从基方法继承的,由此无法直接钦命那一个约束
        //public override void SomeMethod<X>(X x) where X:new()
        //{


        //}
    }

大家在编写程序时,日常蒙受七个模块的效果极度相像,只是二个是拍卖int数据,另1个是处理string数据,或许其余自定义的数据类型,但我们未有办法,只好分别写多个艺术处理每一个数据类型,因为方法的参数类型区别。有未有1种格局,在方式中传唱通用的数据类型,那样不就能够统一代码了呢?泛型的面世正是特地解决这些题材的。读完本篇小说,你会对泛型有越来越深的打听。
缘何要使用泛型
为了打探这几个难点,我们先看下边包车型客车代码,代码省略了壹些内容,但意义是达成1个栈,这几个栈只可以处理int数据类型:

亚洲必赢官网 27

public class Stack

   
子类方法调用虚拟方法的基类达成:它必须钦命要替代泛型基础措施类型所采纳的项目实参。你能够自身显式的内定它,也得以依靠类型推理(倘若恐怕的话)代码如下:

{

    private int[] m_item;

    public int Pop(){...}

    public void Push(int item){...}

    public Stack(int i)

    {

        this.m_item = new int[i];

    }

亚洲必赢官网 28

}

    public class MyBaseClass
    {
        public virtual void SomeMethod<T>(T t) where T:new()
        {
            //亚洲必赢官网 29
        }
    }
    public class MyClass :MyBaseClass
    {
        //正确写法
        public override void SomeMethod<X>(X x)
        {
            base.SomeMethod<X>(x);
            base.SomeMethod(x);
        }
    }

地点代码运转的很好,可是,当我们供给3个栈来保存string类型时,该怎么做吧?很三个人都会想到把上边的代码复制一份,把int改成string不就行了。当然,这样做自作者是绝非其余难点的,但八个大好的顺序是不会那样做的,因为他想到若从此再供给long、Node类型的栈该怎么样做啊?还要再复制吗?优异的程序员会想到用三个通用的数据类型object来促成这些栈:

亚洲必赢官网 30

public class Stack

泛型委托

{

    private object[] m_item;

    public object Pop(){...}

    public void Push(object item){...}

    public Stack(int i)

    {

        this.m_item = new[i];

    }



}

    在有些类中定义的寄托能够接纳该类的泛型参数,代码如下

这一个栈写的不易,他万分灵活,能够吸收任何数据类型,能够说是一劳永逸。但周全地讲,也不是不曾缺陷的,首要表以往:

亚洲必赢官网 31

当Stack处理值类型时,会产出装箱、折箱操作,那将在托管堆上分配和回收大批量的变量,若数据量大,则品质损失相当的惨重。
在处理引用类型时,即使未有装箱和折箱操作,但将用到数据类型的勒迫转换操作,扩张处理器的负责。
在数据类型的吓唬转换上还有更严重的难点(若是stack是Stack的三个实例):
Node1 x = new Node1();

    public class MyClass<T>
    {
        public delegate void GenericDelegate(T t);
        public void SomeMethod(T t)
        {
 
        }
    }
    public GenericMethodDemo()
    {
        MyClass<int> obj = new MyClass<int>();
        MyClass<int>.GenericDelegate del;
        del = new MyClass<int>.GenericDelegate(obj.SomeMethod);
        del(3);
    }

        stack.Push(x);

     Node2 y = (Node2)stack.Pop();

亚洲必赢官网 32

地点的代码在编写翻译时是截然没难点的,但出于Push了三个Node壹类型的数额,但在Pop时却须求改换为Node贰类型,那将出现程序启动时的类型转换非常,但却逃离了编写翻译器的反省。

    委托推理:C#贰.0使您能够将艺术引用的间接分配转变为委托变量。将地点的代码改造如下

本着object类型栈的题目,咱们引进泛型,他能够优雅地缓解那么些题材。泛型用用一个经过的数据类型T来代替object,在类实例化时钦赐T的门类,运转时(Runtime)自动编译为地点代码,运营功能和代码品质都有极大增强,并且保障数据类型安全。

亚洲必赢官网 33

运用泛型
下面是用泛型来重写下面的栈,用三个通用的多少类型T来作为二个占位符,等待在实例化时用三个实际上的花色来取代。让大家来探视泛型的威力:

public class MyClass<T>
    {
        public delegate void GenericDelegate(T t);
        public void SomeMethod(T t)
        {
 
        }
    }
    public GenericMethodDemo()
    {
        MyClass<int> obj = new MyClass<int>();
        MyClass<int>.GenericDelegate del;

public class Stack

        //委托推理
      del = obj.SomeMethod;
        del(3);
     }    

{

    private T[] m_item;

    public T Pop(){...}

    public void Push(T item){...}

    public Stack(int i)

    {

        this.m_item = new T[i];

    }

亚洲必赢官网 34

}

    泛型委托的自律:委托级别的自律只在宣称委托变量和实例化委托时采取,类似于在档次和办法的效应范围中履行的其他任何约束。

类的写法不变,只是引进了通用数据类型T就足以适用于别的数据类型,并且类型安全的。那个类的调用方法:

泛型和反光

//实例化只好保留int类型的类

   
在Net二.0中路,扩大了反光以辅助泛型参数。类型Type未来得以代表带有一定项目标实参(或绑定类型)或未钦点类型的泛型(或称未绑定类型)。像C#一.第11中学那样,您能够经过应用typeof运算符或透过调用每种项目帮忙的GetType()来赢得其余项目标Type。代码如下:

Stack

 LinkedList<int> list = new LinkedList<int>();
 Type type1 = typeof(LinkedList<int>);
 Type type2 = list.GetType();
 Response.Write(type1 == type2);

  a.Push(10);

  a.Push("8888"); //这一行编译不通过,因为类a只接收int类型的数据

  int x = a.Pop();

     typeof和GetType()也得以对泛型参数进行操作,如下

//实例化只好保留string类型的类

亚洲必赢官网 35

Stack

public class MyClass<T>
{
    public void SomeMethod(T t)
    {
        Type type = typeof(T);
        HttpContext.Current.Response.Write(type==t.GetType());
    }
}

b.Push(拾); //那壹行编译不经过,因为类b只接受string类型的数量

亚洲必赢官网 36

  b.Push("8888");

    typeof还是能够对未绑定的泛型举行操作,代码如下

string y = b.Pop();

亚洲必赢官网 37

本条类和object达成的类有完全分歧的区分:

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            Type unboundType = typeof(MyClass<>);
            Response.Write(unboundType.ToString());
        }
    }

  1. 他是项目安全的。实例化了int类型的栈,就不能够处理string类型的多寡,别的数据类型也壹如既往。

  2. 不必装箱和折箱。那一个类在实例化时,按照所传诵的数据类型生费用地代码,当地代码数据类型已规定,所以无需装箱和折箱。

  3. 毋庸类型转换。

    public class MyClass<T>
    {
        public void SomeMethod(T t)
        {
            Type type = typeof(T);
            HttpContext.Current.Response.Write(type==t.GetType());
        }
    }

泛型类实例化的理论
C#泛型类在编译时,先生成人中学等代码IL,通用类型T只是叁个占位符。在实例化类时,根据用户钦定的数据类型代替T并由即时编写翻译器(JIT)生开支地代码,这些当地代码中早就运用了实在的数据类型,等同于用实际类型写的类,所以不一致的封闭类的本地代码是不均等的。依照那个原理,我们能够这么认为:

亚洲必赢官网 38

泛型类的两样的封闭类是分别不一样的数据类型。

   
请留意”<>”的用法。要对含有三个体系参数的未绑定泛型类进行操作,请在”<>”中选拔”,”

例:Stack

   
Type类中添加了新的艺术和属性,用于提供有关该品种的泛型方面包车型地铁反射新闻,见MSDN。

泛型类中数据类型的自律
程序员在编排泛型类时,总是会对通用数据类型T举办有意或下意识地有假想,也正是说那一个T1般的话是无法适应全部项目,但如何界定调用者传入的数据类型呢?那就要求对传播的数据类型实行约束,约束的方式是钦赐T的先世,即持续的接口或类。因为C#的单根继承性,所以约束能够有四个接口,但最七只好有一个类,并且类必须在接口以前。那时就用到了C#二.0的新增关键字:

.net泛型约束  

所谓泛型,即通过参数化类型来兑今后相同份代码上操作种种数据类型。泛型编制程序是1种编程范式,它选择“参数化类型”将品种抽象化,从而达成更为灵活的复用。

在概念泛型类时,能够对客户端代码能够在实例化类时用来项目参数的门类体系施加限制。要是客户端代码尝试选取有个别约束所不允许的品种来实例化类,则会生出编写翻译时不当。那些限制称为约束。约束是利用
where 上下文关键字钦点的。

下表列出了5体系型的约束:

约束 说明

T:struct

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

T:class

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

T:new()

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

T:<基类名>

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

T:<接口名称>

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

T:U

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

 —————————————

1.派生约束

1.常见的

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

2.羁绊放在类的骨子里派生之后

public
class B { }

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

三.能够继续贰个基类和多个接口,且基类在接口前面

public
class B { }

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

二.构造函数约束

1.常见的

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

二.足以将构造函数约束和派生约束组合起来,前提是构造函数约束现身在约束列表的最终

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

三.值约束

1.常见的

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

二.与接口约束同时选取,在最后面(不可能与基类约束,构造函数约束共同利用)

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>{ }

一.
在从泛型基类派生时,能够提供项目实参,而不是基类泛型参数

   
public class SubClass11 : B<int>
    { }

二.万一子类是泛型,而非具体的档次实参,则可以动用子类泛型参数作为泛型基类的钦赐项目

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

三.在子类重复基类的束缚(在运用子类泛型参数时,必须在子类级别重复在基类级别规定的别样自律)
    public class B<T> where T : ISomeInterface { }
    public class SubClass2<T> : B<T> where
T : ISomeInterface { }

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

7.泛型方法(C#2.0泛型机制帮忙在”方法声名上带有类型参数”,那就是泛型方法)

一.泛型方法既能够涵盖在泛型类型中,又有啥不可蕴含在非泛型类型中

public class MyClass5
    {

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

二.泛型方法的表明与调用

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){ }

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

//第2组重载,借使有七个泛型参数
 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;
        }
    }

四.泛型方法的覆写

(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
        { }
    }

8.虚拟方法

public
class BaseClass4<T>
    {
        public virtual T SomeMethod()
        {
            return default(T);
        }
    }
    public class SubClass四 : BaseClass四<int> //使用实参继承的时候方法要采用实参的系列
    {
        public override int SomeMethod()
        {
            return 0;
        }
    }

   
public class SubClass伍<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;
        }
    }

10.编写翻译器允许你将泛型参数字突显式强制转换来任何任何接口,但不可能将其更换成类

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

 

10壹.施用权且的
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) { }
        }
    }

public class Node<T, V> where T : Stack, IComparable

    where V: Stack

{...}

以上的泛型类的封锁注解,T必须是从Stack和IComparable继承,V必须是Stack或从Stack继承,不然将不能够通过编写翻译器的门类检查,编写翻译战败。

通用类型T未有特指,但因为C#中存有的类都以从object继承来,所以他在类Node的编辑中只可以调用object类的格局,那给程序的编纂造成了费力。比如你的类设计只须求帮助二种数据类型int和string,并且在类中要求对T类型的变量比较大小,但这一个却无力回天落到实处,因为object是从未比较大小的法门的。
了消除这么些题材,只需对T举办IComparable约束,那时在类Node里就足以对T的实例执行CompareTo方法了。这一个题材得以扩充到其余用户自定义的数据类型。

若果在类Node里需求对T重新开始展览实例化该如何是好呢?因为类Node中不知道类T到底有如何构造函数。为了消除这些题材,供给使用new约束:

public class Node<T, V> where T : Stack, new()

    where V: IComparable

亟需注意的是,new约束只好是无参数的,所以也供给相应的类Stack必须有一个无参构造函数,不然编写翻译失利。

C#中数据类型有两大类:引用类型和值类型。引用类型如享有的类,值类型一般是言语的最主题类型,如int,
long,
struct等,在泛型的牢笼中,大家也能够大范围地范围类型T必须是引用类型或必须是值类型,分别对应的要紧字是class和struct:

public class Node<T, V> where T : class

    where V: struct

泛型方法
泛型不仅能成效在类上,也可独自用在类的艺术上,他可依照章程参数的门类自动适应种种参数,那样的格局叫泛型方法。看上面包车型客车类:

public class Stack2

{

    public void Push<T>(Stack<T> s, params T[] p)

    {

        foreach (T t in p)

        {

            s.Push(t);

        }

    }

}

原先的类Stack3回只好Push3个数码,那些类Stack2扩充了Stack的效果(当然也能够直接写在Stack中),他能够一遍把多少个数据压入Stack中。个中Push是二个泛型方法,那一个主意的调用示例如下:

Stack

Stack2 x2 = new Stack2();

x2.Push(x, 1, 2, 3, 4, 6);

string s = "";

for (int i = 0; i < 5; i++)

{

    s += x.Pop().ToString();

}    //至此,s的值为64321

泛型中的静态成员变量
在C#1.x中,大家理解类的静态成员变量在不相同的类实例间是共享的,并且她是通过类名访问的。C#二.0中由于引入了泛型,导致静态成员变量的建制出现了有个别转变:静态成员变量在同一封闭类间共享,差别的封闭类间不共享。

那也卓殊简单驾驭,因为差异的封闭类即便有相同的类名称,但出于个别传入了分化的数据类型,他们是一心差异的类,比如:

Stack

Stack

Stack

类实例a和b是同一品种,他们中间共享静态成员变量,但类实例c却是和a、b完全分化的花色,所以不可能和a、b共享静态成员变量。

泛型中的静态构造函数
静态构造函数的平整:只能有三个,且不可能有参数,他只得被.NET运转时自动调用,而不能人工资调整用。

泛型中的静态构造函数的原理和非泛型类是1致的,只需把泛型中的不相同的封闭类了解为不一样的类即可。以下三种景况可刺激静态的构造函数:

  1. 一定的封闭类第二回被实例化。

  2. 特定封闭类中任一静态成员变量被调用。

泛型类中的方法重载
主意的重载在.Net
Framework中被大批量使用,他必要重载具有差异的签名。在泛型类中,由于通用类型T在类编排时并不明显,所以在重载时有点注意事项,那么些事项大家经过以下的例子表明:

public class Node<T, V>

{

    public T add(T a, V b)          //第一个add

    {

        return a;

    }

    public T add(V a, T b)          //第二个add

    {

        return b;

    }

    public int add(int a, int b)    //第三个add

    {

        return a + b;

    }

}

上面包车型地铁类很显明,如果T和V都传入int的话,四个add方法将拥有同等的签名,但以此类还能够经过编写翻译,是不是会挑起调用混淆将在这些类实例化和调用add方法时判断。请看下边调用代码:

Node<int, int> node = new Node<int, int>();

object x = node.add(2, 11);

其1Node的实例化引起了多个add具有相同的签名,但却能调用成功,因为她先期相称了第八个add。但假使剔除了第多个add,上边的调用代码则不能够编写翻译通过,提醒方法爆发的歪曲,因为运维时惊慌失措在首个add和第壹个add之间接选举用。

Node<string, int> node = new Node<string, int>();

    object x = node.add(2, "11");

那两行调用代码可科学编写翻译,因为传播的string和int,使八个add具有区别的签订契约,当然能找到唯壹相称的add方法。

由以上示例可知,C#的泛型是在实例的艺术被调用时检查重载是还是不是产生模糊,而不是在泛型类本身编写翻译时检查。同时还搜查缉获二个首要尺度:

当一般方法与泛型方法具有相同的签署时,会覆盖泛型方法。

泛型类的章程重写
主意重写(override)的首要性难题是格局签名的鉴定识别规则,在那一点上她与方法重载一样,请参考泛型类的法子重载。

泛型的使用限制
本文重假设在类中描述泛型,实际上,泛型还足以用在类形式、接口、结构(struct)、委托等方面运用,使用格局大概相同,就不再讲述。

小结
C#
泛型是付出工具库中的三个珍贵和稀有之宝。它们能够增长质量、类型安全和质量,减弱重复性的编程职务,简化总体编程模型,而那一切都是通过优雅的、可读性强的语法完结的。固然C# 泛型的底子是 C++ 模板,但 C#
通过提供编译时安全和支撑将泛型升高到了多少个新水平。C#
利用了两阶段编译、元数据以及诸如约束和1般方法之类的立异性的定义。毫无疑问,C#
的后天版本将继续开拓进取泛型,以便添加新的职能,并且将泛型扩张到诸如数码访问或本地化之类的其余

.NET Framework 领域。

在C#二.0中,方法能够定义特定于其实践范围的泛型参数,如下所示:
public class MyClass

     //此方法也可不指定方法参数
    public void MyMethod<X>() 
     {
         //
    }
 }    

即使包含类不适用泛型参数,你也可以定义方法特定的泛型参数,如下所示:

public class MyClass
 {
     //指定MyMethod方法用以执行类型为X的参数
    public void MyMethod<X>(X x) 
     {
         //
    }

     //此方法也可不指定方法参数
    public void MyMethod<X>() 
     {
         //
    }
 } 

注意:属性和索引器不能指定自己的泛型参数,它们只能使用所属类中定义的泛型参数进行操作。

在调用泛型方法的时候,你可以提供要在调用场所使用的类型,如下所示:

//调用泛型方法
MyClass myClass = new MyClass();
myClass.MyMethod

泛型推理:在调用泛型方法时,C#编译器足够聪明,基于传入的参数类型来推断出正确的类型,并且它允许完全省略类型规范,如下所示:

//泛型推理机制调用泛型方法
MyClass myClass = new MyClass();
myClass.MyMethod(3);

注意:泛型方法无法只根据返回值的类型推断出类型,代码如下:

 public GenericMethodDemo()
  {        
     MyClass myClass = new MyClass();
     /****************************************************
     无法从用法中推理出方法“GenericMethodDemo.MyClass.MyMethod<T>()”的类型参数。
    请尝试显式指定类型参数。
    ***************************************************/
     int number = myClass.MyMethod();
  }

 public class MyClass
 {
     public T MyMethod<T>() 
     {
         //
    }
 } 

泛型方法中泛型参数的约束,如下:

public class MyClass
 {

     public void MyMethod<X>(X x) where X:IComparable<X>
     {
         //
    }
 }


您无法为类级别的泛型参数提供方法级别的约束。类级别泛型参数的所有约束都必须在类作用范围中定义,代码如下所示

public class MyClass<T>
 {

     public void MyMethod<X>(X x,T t) where X:IComparable<X> where T:IComparer<T>
     {
         //
    }
 } 

而上边包车型客车代码是毋庸置疑的

public class MyClass<T> where T:IComparable<T>
 {

     public void MyMethod<X>(X x,T t) where X:IComparable<X> 
     {
         //
    }
 } 

泛型参数虚方法的重写:子类方法必须重新定义该方法特定的泛型参数,代码如下

public class MyBaseClass
 {
     public virtual void SomeMethod<T>(T t)
     {
         //
    }
 }
 public class MyClass :MyBaseClass
 {
     public override void SomeMethod<X>(X x)
     {

     }
 } 

并且子类中的泛型方法不能再度基类泛型方法的封锁,那点和泛型类中的虚方法重写是有分其他,代码如下

public class MyBaseClass
 {
     public virtual void SomeMethod<T>(T t) where T:new()
     {
         //
    }
 }
 public class MyClass :MyBaseClass
 {
     //正确写法
    public override void SomeMethod<X>(X x)
     {

     }

     ////错误 重写和显式接口实现方法的约束是从基方法继承的,因此不能直接指定这些约束
    //public override void SomeMethod<X>(X x) where X:new()
     //{

     //}
} 

子类方法调用虚拟方法的基类实现:它必须指定要代替泛型基础方法类型所使用的类型实参。你可以自己显式的指定它,也可以依靠类型推理(如果可能的话)代码如下:

public class MyBaseClass
 {
     public virtual void SomeMethod<T>(T t) where T:new()
     {
         //
    }
 }
 public class MyClass :MyBaseClass
 {
     //正确写法
    public override void SomeMethod<X>(X x)
     {
         base.SomeMethod<X>(x);
         base.SomeMethod(x);
     }
 } 

泛型委托

在某个类中定义的委托可以使用该类的泛型参数,代码如下

public class MyClass<T>
 {
     public delegate void GenericDelegate(T t);
     public void SomeMethod(T t)
     {

     }
 }
 public GenericMethodDemo()
 {
     MyClass<int> obj = new MyClass<int>();
     MyClass<int>.GenericDelegate del;
     del = new MyClass<int>.GenericDelegate(obj.SomeMethod);
     del(3);
 } 

委托推理:C#2.0使你可以将方法引用的直接分配转变为委托变量。将上面的代码改造如下

public class MyClass

     }
 }
 public GenericMethodDemo()
 {
     MyClass<int> obj = new MyClass<int>();
     MyClass<int>.GenericDelegate del;

     //委托推理
  del = obj.SomeMethod;
     del(3);
  }     

泛型委托的约束:委托级别的约束只在声明委托变量和实例化委托时使用,类似于在类型和方法的作用范围中实施的其他任何约束。

泛型和反光

在Net2.0当中,扩展了反射以支持泛型参数。类型Type现在可以表示带有特定类型的实参(或绑定类型)或未指定类型的泛型(或称未绑定类型)。像C#1.1中那样,您可以通过使用typeof运算符或通过调用每个类型支持的GetType()来获得任何类型的Type。代码如下:

LinkedList

 typeof和GetType()也可以对泛型参数进行操作,如下

public class MyClass

typeof还可以对未绑定的泛型进行操作,代码如下

protected void Page_Load(object sender, EventArgs e)
 {
     if (!IsPostBack)
     {
         Type unboundType = typeof(MyClass<>);
         Response.Write(unboundType.ToString());
     }
 }

 public class MyClass<T>
 {
     public void SomeMethod(T t)
     {
         Type type = typeof(T);
         HttpContext.Current.Response.Write(type==t.GetType());
     }
 } 


请注意"<>"的用法。要对带有多个类型参数的未绑定泛型类进行操作,请在"<>"中使用","
Type类中添加了新的方法和属性,用于提供有关该类型的泛型方面的反射信息,见MSDN。

.net泛型约束

所谓泛型,即经过参数化类型来兑现在同①份代码上操作多样数据类型。泛型编制程序是1种编制程序范式,它选择“参数化类型”将项目抽象化,从而达成更为灵活的复用。

在概念泛型类时,能够对客户端代码能够在实例化类时用来项目参数的类型种类施加限制。假如客户端代码尝试运用某些约束所不容许的项目来实例化类,则会时有发生编写翻译时不当。那几个限制称为约束。约束是选拔where 上下文关键字钦赐的。

下表列出了七种档次的羁绊:

自律表达:

T:struct

花色参数必须是值类型。能够钦命除 Nullable 以外的其余值类型。

T:class

项目参数必须是援引类型,包含任何类、接口、委托或数组类型。

T:new()

品类参数必须具有无参数的公家构造函数。当与别的约束共同使用时,new()
约束必须最终内定。

T:<基类名>

连串参数必须是内定的基类或派生自钦赐的基类。

T:<接口名称>

类别参数必须是钦定的接口或落到实处内定的接口。能够钦点四个接口约束。约束接口也能够是泛型的。

T:U

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


壹.派生封锁

1.常见的

public class MyClass5

二.束缚放在类的莫过于派生之后

public class B { }

public class MyClass6

叁.能够一连三个基类和多少个接口,且基类在接口前边

public class B { }

public class MyClass7

贰.构造函数约束

1.常见的

public class MyClass8

二.得以将构造函数约束和派生约束组合起来,前提是构造函数约束出今后约束列表的尾声

public class MyClass8

三.值约束

1.常见的

public class MyClass9

二.与接口约束同时采纳,在最前头(不可能与基类约束,构造函数约束共同利用)

public class MyClass11

4.引用约束

1.常见的

public class MyClass10

伍.三个泛型参数

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

陆.继承和泛型

public class B

  1. 在从泛型基类派生时,能够提供项目实参,而不是基类泛型参数

    public class SubClass11 : B

二.假使子类是泛型,而非具体的花色实参,则足以采取子类泛型参数作为泛型基类的钦定项目

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

叁.在子类重复基类的约束(在应用子类泛型参数时,必须在子类级别重复在基类级别规定的别样自律)
public class B

四.构造函数约束
public class B

7.泛型方法(C#二.0泛型机制支持在”方法声名上带有类型参数”,那就是泛型方法)

一.泛型方法既能够包括在泛型类型中,又足以分包在非泛型类型中

public class MyClass5
{

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

二.泛型方法的扬言与调用

public class MyClass5
{
public void MyMethod

三.泛型方法的重载

//第3组重载
void MyMethod1

void MyMethod1(U u, int i){ }

//第一组重载
void MyMethod2

//第一组重载,要是有多个泛型参数
void MyMethod3

//第陆组重载

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

(2)public class MyBaseClass2
{
public virtual void MyMothed

8.虚拟方法

public class BaseClass4

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

玖.编写翻译器只同意将泛型参数隐式强制转换成 Object 或约束钦赐的品种

class MyClass

变通方法:使用权且的 Object 变量,将泛型参数强制转换成其余任何项目

class MyClass2

10.编译器允许你将泛型参数字突显式强制转换成任何任何接口,但不能将其更换成类

class MyClass1

10①.使用目前的 Object 变量,将泛型参数强制转换成别的任何项目

class MyClass2

十二.使用is和as运算符

public class MyClass3

网站地图xml地图