• 技术文章 >后端开发 >C#.Net教程

    C#2.0 Specification(泛型一)

    黄舟黄舟2017-01-03 10:22:21原创395

    由于这一章非常长可能需要分几篇:)

    20.泛型

    20.1泛型类声明

    泛型类声明是一个需要提供类型参数以形成实际类型的类的声明。



    类声明可以有选择地定义类型参数。

    class-declaration: (类声明)
    attributesopt class-modifiersopt class identifieropt type-parameter-listopt class –baseopt type-parameter-constraints-clauseopt class-body;opt (特性可选 类修饰符可选 类标识符可选 类型参数列表可选 基类可选 类型参数约束语句可选 类体; 可选 )
    除非提供了类型参数列表,类声明可以不提供类型参数化约束语句。

    提供了类型参数列表的类声明是一个泛型类声明。此外,任何嵌入到泛型类声明或泛型结构声明中的类,自身是一个泛型类声明,因为必须提供包含类型的类型参数以创建构造类型(constructed type);

    泛型类通过使用构造类型而被引用(§20.5)。给定泛型类声明

    class List<T>{}
    这是构造类型的一些例子,List<T>,List<int>和List<List<string>>。构造类型可以使用一个或多个参数,例如List<T>被称为开放构造类型(open constructed type)。不使用类型参数的构造类型,例如List<int>被称为封闭构造类型(closed constructed type)。

    泛型类型不可以被“重载”;也就是说,和普通类型一样在一个作用域内,泛型类型必须被唯一地命名。


    class C{}
    class C<V>{}//错误,C定义了两次
    class C<U,V>{}//错误,C定义了两次
    然而在非限定类型名字查找(§20.9.3)中使用的类型查找规则和成员访问(§20.9.4),确实考虑到了类型参数的个数。

    20.1.1类型参数

    类型参数可以在一个类声明上提供。每个类型参数是一个简单的标识符,它指示了用来创建一个构造类型的类型参数的占位符。类型参数是在后面将要被提供的类型的形式占位符。相反,类型参数§20.5.1)只是在构造类型被引用时,实际类型的一个替代。

    type-parameter-list:(类型参数列表:)
    <type-parameters> (<类型参数>)
    type-parameters:(类型参数:)
    type-parameter(类型参数)
    type-parameters type-parameter(类型参数,类型参数)
    type-parameter:(类型参数:)
    attributesopt identifier(特性可选 标识符)

    在类声明中的每个类型参数在类的声明空间(§3.3)定义了一个名字。由此,它不能和另一个类型参数或在类中声明的成员有同样的名字。类型参数不能和类型自身有同样的名字。

    在一个类中的类型参数的作用域(§3.7),包括基类 、 类型参数约束语句和类体。不像类的成员,它没有扩展到派生类。在其作用域之内,类型参数可以被用作一个类型。

    type(类型):

    value-type(值类型)
    reference-type(引用类型)
    type-parameter(类型参数)
    由于类型参数可以被许多不同的实际类型实参所实例化,类型参数与其他类型相比将略微有一些不同的操作和限制。包括如下内容。

    类型参数不能用于直接声明一个基类型或者接口
    对于在类型参数上的成员查找规则,如果约束存在,则依赖于应用到该类型参数的约束。更详细地说明参看§20.7.4。



    类型参数可行的转换依赖于应用到该类型参数上的约束(如果有的话)。详细地说明参看§20.7.4。
    字面null不能被转换到由类型参数所给定的类型,除非类型参数是由一个类约束(§20.7.4)所约束。然而可以使用一个默认值表达式(§20.8.1)代替。此外,由一个类型参数给定的类型的值可以使用“==”和“!=”(§20.8.4)与null进行比较。
    如果类型参数通过一个构造函数约束(constructor-constraint)(§20.7)而约束,new表达式只能用过一个类型参数而被使用。
    类型参数不能用于特性内的任何地方。
    类型参数不能用于成员访问,或者表示一个静态成员或者嵌套类型的类型名字(§20.9.1、§20.9.4)。
    在不安全代码中,类型参数不能被用作托管类型(§18.2)。

    作为一种类型,类型参数纯粹只是一个编译时构件。在运行时,每个类型参数被绑定到运行时类型,它是通过泛型类型声明所提供的类型实参所指定的。为此,在运行时,使用类型参数声明的变量类型是一个封闭类型(closed type)(§20.5.2)。所有语句和表达式在运行时执行所使用的类型参数,都是由那个参数作为类型实参而提供的实际类型。

    20.1.2实例类型

    每个类声明都有与之关联的构造类型,即实例类型(instance type)。对于一个泛型类声明,实例类型通过创建一个来自于类型声明的构造类型(§20.4)而形成,它使用对应于类型参数的每一个类型实参。由于实例化类型使用类型参数,在类型参数作用域内(类声明之内),它是唯一有效的。实例类型在类声明中是this的类型。对于非泛型类,实例类型只是一个声明类型。下面展示了几个声明类,以及它们的实例类型。

    class A<T> //实例类型:A<T>
    {
    class B{} //实例类型:A<T>.B
    class C<U>{} //实例类型:A<T>.C<U>
    }
    class D{} //实例类型:D

    20.1.3基类规范

    在类声明中指定的基类可以是一个构造类型(§20.5)。一个基类其自身不能是一个类型参数,但在其作用域内可以包含类型参数。


    class Extend<V>: V{}//错误,类型参数被用作基类
    泛型类声明不能使用System.Attribute作为直接或间接基类。

    在一个类声明中指定的基接口可以是构造接口类型(§20.5)。基接口自身不能是类型参数,但在其作用域内可以包含类型参数,下面的代码演示了如何实现和扩展构造类型。

    class C<U,V>{}
    Interface I1<V>{}
    class D:C<string , int>,I1<string>{}
    class E<T>:C<int,T> ,I1<T>{}

    泛型类型声明的基接口必须满足§20.3.1中所描述的唯一性规则。

    从基类或接口重写或实现方法的类的方法,必须提供特定类型的合适方法。下面的代码演示了方法如何被重写和实现。这将会在§20.1.10中进一步解释。

    class C<U,V>
    {
    public virtual void M1(U x , List<V> y){…}
    }
    interface I1<V>
    {
    V M2(V x);
    }
    class D:C<string , int>,I1<string>
    {
    public override void M1(string x , List<int> y){…}
    public string M2(string x){…}
    }

    20.1.4泛型类的成员

    泛型类的所有成员都可以直接地或者作为构造类型的一部分,从任何封闭类(enclosing class)中使用类型参数。当特定的封闭构造类型在运行时被使用时,类型参数的每次使用都由构造类型所提供的实际类型实参所代替。例如


    class C<V>
    { 
    public V f1; 
    public C<V> f2=null;
    public C(V x){
    this.f1 = x;
    this.f2 = this;
    }
    }
    class Application
    {
    static void Main(){
    C<int> x1= new C<int >(1);
    Console.WriteLine(x1.f1); //打印1
    C<double> x2 = new C<double>(3.1415);
    Console.WriteLine(x2.f1); //打印 3.1415
    }
    }

    在实例函数成员之内,this的类型就是声明的实例类型(§20.1.2)。

    除了使用类型参数作为类型和成员,在泛型类声明中也遵循和非泛型类成员相同的规则。适用于特定种类成员的附加规则将在后面几节进行讨论。

    20.1.5泛型类中的静态字段

    在一个泛型类声明中的静态变量,在相同封闭构造类型(§20.5.2)所有实例中被共享,但在不同封闭构造类型的实例中[1],是不被共享的。这些规则不管静态变量的类型包含那种类型参数都适用。

    例如

    class C<V>
    {
    static int count = 0;
    public C()
    {
    count++;
    }
    public static int Count{
    get{return count;}
    }
    }
    class Application
    {
    static void Main()
    {
    C<int> x1 = new C<int>();
    Console.WriteLine(C<int>.Count);//打印 1
    C<double> x2 = new C<double>();
    Console.WriteLine(C<int>.Count);//打印 1
    C<int> x3 = new C<int>();
    Console.WriteLine(C<int>.Count);//打印 2
    }
    }

    [1] 这是很容易理解的,因为在运行时,不同的封闭构造类型,是属于不同的类型,比如List<int> 和List<string> 这二者的实例是不能共享静态变量的。

    以上就是C#2.0 Specification(泛型一)的内容,更多相关内容请关注PHP中文网(m.sbmmt.com)!

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    专题推荐:C#,Specification
    上一篇:C# 2.0 Specification (四) 下一篇:C#2.0 Specification(泛型二)

    相关文章推荐

    • c语言中形参的缺省存储类别是什么• asp.net core mvc实现文件上传实例• C#的多线程机制初探(3)• C# 2.0 Specification (泛型三)

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网