Rumah > pembangunan bahagian belakang > Tutorial C#.Net > C#2.0 Specification(泛型一)

C#2.0 Specification(泛型一)

黄舟
Lepaskan: 2017-01-03 10:22:21
asal
1381 orang telah melayarinya

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

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

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


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

20.1.1类型参数

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

type-parameter-list:(类型参数列表:)
(<类型参数>)
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
Salin selepas log masuk

20.1.3基类规范

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


class Extend: 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>{}
Salin selepas log masuk

泛型类型声明的基接口必须满足§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){…}
}
Salin selepas log masuk

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
}
}
Salin selepas log masuk

在实例函数成员之内,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
}
}
Salin selepas log masuk

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

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


Label berkaitan:
sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan