Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C-sharp language specification.2004.pdf
Скачиваний:
14
Добавлен:
23.08.2013
Размер:
2.55 Mб
Скачать

Chapter 26 Generics

126. Generics

226.1 Generic class declarations

3A generic class declaration is a declaration of a class that requires type arguments to be supplied in order to

4form actual types.

5[Note: A class declaration (§17.1), can optionally define type parameters and their associated constraints:

6class-declaration:

7

attributesopt class-modifiersopt partialopt class identifier type-parameter-listopt

8

class-baseopt type-parameter-constraints-clausesopt class-body ;opt

9A class declaration shall not supply type-parameter-constraints-clauses (§26.7) unless it also supplies a

10type-parameter-list (§26.1.1).

11A class declaration that supplies a type-parameter-list is a generic class declaration. end note]

12Any class nested inside a generic class declaration or a generic struct declaration (§26.2) is itself a generic

13class declaration, since type parameters for the containing type shall be supplied to create a constructed type.

14Generic class declarations follow the same rules as non-generic class declarations except where noted.

15Generic class declarations can be nested inside non-generic class declarations.

16A generic class is referenced using a constructed type (§26.5). [Example: Given the generic class declaration

17class List<T> {}

18some examples of constructed types are List<T>, List<int> and List<List<string>>. end example]

19A constructed type that uses one or more type parameters, such as List<T>, is called an open constructed

20type (§26.5). A constructed type that uses no type parameters, such as List<int>, is called a closed

21constructed type (§26.5).

22Generic types can be “overloaded” on the number of type parameters; that is two type declarations within

23the same namespace or outer type declaration can use the same identifier as long as they have a different

24number of type parameters.

25class C {}

26

class C<V> {}

// OK

27

struct C<U,V> {}

// OK

28

class C<A,B> {}

// Error, C with two type parameters defined twice

29The type lookup rules used during type name resolution (§10.8), simple name resolution (§14.5.2) and

30member access (§14.5.4) respect the number of type parameters.

31The base interfaces of a generic class declaration shall satisfy the uniqueness rule described in §26.3.1.

3226.1.1 Type parameters

33Type parameters can be supplied in a class declaration. Each type parameter is a simple identifier that

34denotes a placeholder for a type argument supplied to create a constructed type. A type parameter is a formal

35placeholder for a type that will be supplied later. By constrast, a type argument (§26.5.1) is the actual type

36that is substituted for the type parameter when a constructed type is created.

37type-parameter-list:

38< type-parameters >

39type-parameters:

40

attributesopt type-parameter

41

type-parameters , attributesopt type-parameter

397

C# LANGUAGE SPECIFICATION

1

2

type-parameter: identifier

3Each type parameter in a class declaration defines a name in the declaration space (§10.3) of that class.

4Thus, it cannot have the same name as another type parameter or a member declared in that class. A type

5parameter shall not have the same name as the type itself.

6The scope (§10.7) of a type parameter on a class includes the class-base, type-parameter-constraints-

7clauses, and class-body. Unlike members of a class, this scope does not extend to derived classes. Within its

8scope, a type parameter can be used as a type.

9Since a type parameter can be instantiated with many different actual type arguments, type parameters have

10slightly different operations and restrictions than other types. [Note: These include:

11A type parameter cannot be used directly to declare a base class or interface (§17.1.2).

12The rules for member lookup on type parameters depend on the constraints, if any, applied to the type

13parameter. They are detailed in §26.7.2.

14The available conversions for a type parameter depend on the constraints, if any, applied to the type

15parameter. They are detailed in §26.7.4.

16The literal null cannot be converted to a type given by a type parameter, except if the type parameter is

17known to be a reference type (§26.7.4). However, a default value expression (§14.5.13) can be used

18instead. In addition, a value with a type given by a type parameter can be compared with null using ==

19and != (§14.9.6) unless the type parameter has the value type constraint (§26.7.4).

20A new expression (§14.5.10.1) can only be used with a type parameter if the type parameter is

21constrained by a constructor-constraint or the value type constraint (§26.7).

22A type parameter cannot be used anywhere within an attribute (§24.2).

23A type parameter cannot be used in a member access or type name to identify a static member or a

24nested type (§10.8, §14.5.4).

25In unsafe code, a type parameter cannot be used as an unmanaged-type (§25.2).

26end note]

27As a type, type parameters are purely a compile-time construct. At run-time, each type parameter is bound to

28a run-time type that was specified by supplying a type argument to the generic type declaration. Thus, the

29type of a variable declared with a type parameter will, at run-time, be a closed constructed type (§26.5.2).

30The run-time execution of all statements and expressions involving type parameters uses the actual type that

31was supplied as the type argument for that parameter.

3226.1.2 The instance type

33Each class declaration has an associated constructed type, the instance type. For a generic class declaration,

34the instance type is formed by creating a constructed type (§26.5) from the type declaration, with each of the

35supplied type arguments being the corresponding type parameter. Since the instance type uses the type

36parameters, it can only be used where the type parameters are in scope; that is, inside the class declaration.

37The instance type is the type of this for code written inside the class declaration. For non-generic classes,

38the instance type is simply the declared class. [Example: The following shows several class declarations

39along with their instance types:

40

class A<T>

// instance type: A<T>

41

{

 

42

class B {}

// instance type: A<T>.B

43

class C<U> {}

// instance type: A<T>.C<U>

44

}

 

45

class D {}

// instance type: D

46

end example]

 

398

Chapter 26 Generics

126.1.3 Members of generic classes

2All members of a generic class can use type parameters from any enclosing class, either directly or as part of

3a constructed type. When a particular closed constructed type (§26.5.2) is used at run-time, each use of a

4type parameter is replaced with the actual type argument supplied to the constructed type. [Example:

5class C<V>

6{

7

public V F1;

8

public C<V> F2 = null;

9

public C(V x) {

10

this.F1 = x;

11

this.F2 = this;

12}

13}

14class Application

15{

16

static void Main() {

 

17

C<int> x1

= new C<int>(1);

 

18

Console.WriteLine(x1.F1);

// Prints 1

19

C<double>

x2 = new C<double>(3.1415);

20

Console.WriteLine(x2.F1);

// Prints 3.1415

21}

22}

23end example]

24Within instance function members, the type of this is the instance type (§26.1.2) of the containing

25declaration.

26Apart from the use of type parameters as types, members in generic class declarations follow the same rules

27as members of non-generic classes. Additional rules that apply to particular kinds of members are discussed

28in the following subclauses.

2926.1.4 Static fields in generic classes

30A static variable in a generic class declaration is shared amongst all instances of the same closed constructed

31type (§26.5.2), but is not shared amongst instances of different closed constructed types. These rules apply

32regardless of whether the type of the static variable involves any type parameters or not.

33[Example:

34class C<V>

35{

36

static

int count = 0;

37

public C() {

38

count++;

39

}

 

40

public static int Count {

41

get { return count; }

42}

43}

44

45class Application

46{

47

static void Main() {

 

48

C<int> x1 = new C<int>();

 

49

Console.WriteLine(C<int>.Count);

// Prints 1

50

C<double> x2 = new C<double>();

 

51

Console.WriteLine(C<double>.Count); // Prints 1

52

Console.WriteLine(C<int>.Count);

// Prints 1

399

 

C# LANGUAGE SPECIFICATION

 

1

C<int> x3 = new C<int>();

 

2

Console.WriteLine(C<int>.Count);

// Prints 2

3}

4}

5end example]

626.1.5 Static constructors in generic classes

7A static constructor in a generic class is used to initialize static fields and to perform other initialization for

8each different closed constructed type that is created from that generic class declaration. The type parameters

9of the generic type declaration are in scope, and can be used, within the body of the static constructor.

10A new closed constructed class type is initialized the first time that either:

11An instance of the closed constructed type is created.

12Any of the static members of the closed constructed type are referenced.

13To initialize a new closed constructed class type, first a new set of static fields (§26.1.4) for that particular

14closed constructed type is created. Each of the static fields is initialized to its default value (§12.2). Next, the

15static field initializers (§17.4.5.1) are executed for those static fields. Finally, the static constructor is

16executed.

17Because the static constructor is executed exactly once for each closed constructed class type, it is a

18convenient place to enforce run-time checks on the type parameter that cannot be checked at compile-time

19via constraints (§26.7). [Example: The following type uses a static constructor to enforce that the type

20argument is an enum:

21class Gen<T> where T: struct

22{

23

static Gen() {

24

if (!typeof(T).IsEnum) {

25

throw new ArgumentException("T must be an enum");

26

}

27}

28}

29end example]

3026.1.6 Accessing protected members

31[Note: The accessibility domain (§10.5.2) of a protected member declared in a generic class includes the

32program text of all class declarations derived from any type constructed from that generic class. In the

33example:

34class C<T>

35{

36protected static T x;

37}

38class D: C<string>

39{

40

static void

Main() {

41

C<int>.x

= 5;

42}

43}

44The reference to protected member C<int>.x in D is valid even though the class D derives from

45C<string>.

46end note]

47Within a generic class declaration, access to inherited protected instance members (§10.5.3) is permitted

48through an instance of any class type constructed from the generic class. [Example: In the following code

400

Соседние файлы в предмете Электротехника