泛型计算,泛型方法

前言

所谓泛型,即经过参数化类型来落到实处在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中,方法能够定义特定于其进行范围的泛型参数,如下所示:

一)、表示可透过索引访问的靶子的强类型列表;提供用于对列表实行搜索、排序和操作的章程。
二)、是ArrayList类的泛型等效类。
3)、能够应用3个整数索引访问此汇集中的成分;索引从零 初始。
四)、可以接收null空引用(VB中的Nothing)。
伍)、允许再一次成分

泛型方法

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

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

public class B { }

public class MyClass6 : B where T : IComparable { }

叁.方可继续2个基类和多少个接口,且基类在接口后面

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

二.与接口约束同时利用,在最前面(无法与基类约束,构造函数约束共同利用)

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:欢迎扫描下方2维码,参预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
赢得或设置该内部数据结构在不调整大小的图景下能够容纳的元素总数。

一、 约束

  下表列出了5类别型的羁绊:

约束 说明

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

2.封锁放在类的莫过于派生之后

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

三.在子类重复基类的牢笼(在应用子类泛型参数时,必须在子类级别重复在基类级别规定的任何自律)
    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

叁、泛型方法

(C#二.0泛型机制帮助在”方法声名上含蓄类型参数”,那正是泛型方法)

1.泛型方法既能够涵盖在泛型类型中,又有什么不可包括在非泛型类型中

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

叁.泛型方法的重载

//第一组重载
 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

4、虚拟方法

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

7、 泛型参数强制转换成别的任何类型

使用一时半刻的 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

伍、常用方法实例

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

(一)创立及初阶化:
List

美高梅开户网址 22

(二)添加1个要素 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)
        {
            
        }
    }

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

美高梅开户网址 24

(4)在index地方添加三个因素 Insert(int index,T item)
mlist.Insert(1,”p”);

并且子类中的泛型方法不可能重新基类泛型方法的束缚,那或多或少和泛型类中的虚方法重写是有分其他,代码如下

(5)遍历List中元素
foreach(T element in mlist)
T的品类与mlist注解时1致{  Console.WriteLine(element);}

美高梅开户网址 25

(陆)删除成分
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数据,另贰个是处理string数据,大概别的自定义的数据类型,但我们从不艺术,只可以分别写三个办法处理每种数据类型,因为方法的参数类型不一致。有未有一种办法,在艺术中传来通用的数据类型,那样不就足以统一代码了啊?泛型的出现正是特意消除那些题材的。读完本篇文章,你会对泛型有更加深的询问。
缘何要选拔泛型
为了打探那一个题材,我们先看上面包车型大巴代码,代码省略了部分内容,但效益是达成二个栈,那几个栈只可以处理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);
        }
    }

上面代码运转的很好,不过,当大家要求三个栈来保存string类型时,该如何做呢?很两个人都会想到把地点的代码复制1份,把int改成string不就行了。当然,这样做作者是尚未别的难点的,但2个可观的先后是不会这么做的,因为她想到若从此再必要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来作为1个占位符,等待在实例化时用一个实在的档次来代表。让我们来探视泛型的威力:

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类型的类

   
在Net2.0在那之中,扩充了反光以支撑泛型参数。类型Type以往能够表示带有一定项目标实参(或绑定类型)或未钦点类型的泛型(或称未绑定类型)。像C#1.第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(10); //那一行编译不通过,因为类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只是2个占位符。在实例化类时,依据用户钦赐的数据类型代替T并由即时编写翻译器(JIT)生费用地代码,这一个地面代码中一度选用了实际上的数据类型,等同于用实际类型写的类,所以差别的封闭类的本地代码是不等同的。根据这一个原理,大家得以那样认为:

美高梅开户网址 38

泛型类的不相同的封闭类是个别分化的数据类型。

   
请小心”<>”的用法。要对含蓄多少个品种参数的未绑定泛型类实行操作,请在”<>”中选拔”,”

例:Stack

   
Type类中添加了新的主意和特性,用于提供有关该品种的泛型方面包车型大巴反射音讯,见MSDN。

泛型类中数据类型的牢笼
程序员在编排泛型类时,总是会对通用数据类型T实行有意或下意识地有假想,也正是说这一个T壹般的话是不能够适应全数类型,但什么界定调用者传入的数据类型呢?那就要求对传播的数据类型进行约束,约束的章程是钦点T的祖宗,即持续的接口或类。因为C#的单根继承性,所以约束能够有多少个接口,但最四只好有一个类,并且类必须在接口在此之前。那时就用到了C#2.0的新增关键字:

.net泛型约束  

所谓泛型,即因此参数化类型来完成在平等份代码上操作种种数据类型。泛型编程是1种编制程序范式,它利用“参数化类型”将项目抽象化,从而完成更为灵活的复用。

在概念泛型类时,能够对客户端代码能够在实例化类时用来项目参数的体系种类施加限制。如果客户端代码尝试使用有个别约束所不允许的类型来实例化类,则会发出编写翻译时不当。这个限制称为约束。约束是应用
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() { }

二.能够将构造函数约束和派生约束组合起来,前提是构造函数约束出现在约束列表的终极

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

6.继承和泛型

public
class B<T>{ }

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

   
public class SubClass11 : B<int>
    { }

二.1旦子类是泛型,而非具体的类型实参,则足以接纳子类泛型参数作为泛型基类的钦赐项目

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

柒.泛型方法(C#二.0泛型机制支持在”方法声名上含蓄类型参数”,那正是泛型方法)

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

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

三.泛型方法的重载

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

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

//第3组重载
 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 : BaseClass四<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;
        }
    }

10.编译器允许你将泛型参数字呈现式强制转换成其余任何接口,但无法将其更换成类

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

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#中数据类型有两大类:引用类型和值类型。引用类型如全体的类,值类型1般是言语的最宗旨项目,如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);

        }

    }

}

原来的类Stack二遍只可以Push2个数码,这么些类Stack二扩张了Stack的作用(当然也能够平素写在Stack中),他能够2遍把五个数据压入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#一.x中,我们掌握类的静态成员变量在区别的类实例间是共享的,并且他是经过类名访问的。C#二.0中出于引入了泛型,导致静态成员变量的编写制定出现了一些转移:静态成员变量在同样封闭类间共享,差异的查封类间不共享。

那也格外简单驾驭,因为不一致的封闭类固然有雷同的类名称,但出于个别传入了不一致的数据类型,他们是一点一滴两样的类,比如:

Stack

Stack

Stack

类实例a和b是平等档次,他们中间共享静态成员变量,但类实例c却是和a、b完全两样的类型,所以不能够和a、b共享静态成员变量。

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

泛型中的静态构造函数的规律和非泛型类是千篇壹律的,只需把泛型中的不一样的封闭类精晓为不一致的类即可。以下三种状态可刺激静态的构造函数:

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

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

泛型类中的方法重载
艺术的重载在.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);

以此Node的实例化引起了多个add具有同样的签订契约,但却能调用成功,因为他先期相称了第5个add。但1旦去除了第三个add,上边的调用代码则无从编写翻译通过,提示方法发生的模糊,因为运营时心慌意乱在第三个add和第二个add之间采用。

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

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

那两行调用代码可科学编写翻译,因为传播的string和int,使四个add具有不一致的签署,当然能找到唯一相称的add方法。

由上述示例可见,C#的泛型是在实例的不二等秘书籍被调用时检查重载是还是不是产生模糊,而不是在泛型类自己编写翻译时检查。同时还得出3个根本尺度:

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

泛型类的办法重写
办法重写(override)的主要难点是办法签名的鉴定区别规则,在那或多或少上她与艺术重载1样,请参考泛型类的方法重载。

泛型的选拔限制
正文重借使在类中描述泛型,实际上,泛型还是能够用在类形式、接口、结构(struct)、委托等方面运用,使用办法差不离相同,就不再讲述。

小结
C#
泛型是开发工具库中的3个珍贵和稀有之宝。它们得以进步质量、类型安全和品质,减弱重复性的编程职责,简化总体编制程序模型,而那1切都以通过优雅的、可读性强的语法实现的。固然C# 泛型的根底是 C++ 模板,但 C#
通过提供编写翻译时安全和支撑将泛型提升到了一个新水平。C#
利用了两品级编写翻译、元数据以及诸如约束和一般方法之类的立异性的定义。毫无疑问,C#
的今后版本将继承上扬泛型,以便添加新的效应,并且将泛型扩充到比如数码访问或本地化之类的别的

.NET Framework 领域。

在C#2.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泛型约束

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

在概念泛型类时,能够对客户端代码能够在实例化类时用于项目参数的品各类类施加限制。假使客户端代码尝试运用有个别约束所区别意的连串来实例化类,则会发生编写翻译时不当。那些限制称为约束。约束是运用
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

三.足以一连1个基类和八个接口,且基类在接口后面

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

2.一旦子类是泛型,而非具体的门类实参,则能够使用子类泛型参数作为泛型基类的钦赐项目

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

3.在子类重复基类的牢笼(在接纳子类泛型参数时,必须在子类级别重复在基类级别规定的其余约束)
public class B

四.构造函数约束
public class B

柒.泛型方法(C#二.0泛型机制帮助在”方法声名上含蓄类型参数”,那正是泛型方法)

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

public class MyClass5
{

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

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

public class MyClass5
{
public void MyMethod

三.泛型方法的重载

//第3组重载
void MyMethod1

void MyMethod1(U u, int i){ }

//第二组重载
void MyMethod2

//第二组重载,如果有四个泛型参数
void MyMethod3

//第6组重载

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

(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地图