Home  >  Article  >  Backend Development  >  C#2.0 Specification (Generics 1)

C#2.0 Specification (Generics 1)

黄舟
黄舟Original
2017-01-03 10:22:211185browse

Since this chapter is very long, it may need to be divided into several chapters:)

20. Generics

20.1 Generic class declaration

A generic class declaration is a declaration of a class that requires type parameters to be provided to form an actual type.



Class declarations can optionally define type parameters.

class-declaration: (Class declaration)
attributesopt class-modifiersopt class identifieropt type-parameter-listopt class –baseopt type-parameter-constraints-clauseopt class-body;opt (attribute optional class modifier Optional class identifier Optional type parameter list Optional base class Optional type parameter constraint statement Optional class body; Optional)
Unless a type parameter list is provided, the class declaration does not need to provide a type parameterized constraint statement.

A class declaration that provides a type parameter list is a generic class declaration. In addition, any class embedded in a generic class declaration or generic struct declaration is itself a generic class declaration because type parameters of the containing type must be provided to create a constructed type;

Generic Type classes are referenced using constructed types (§20.5). Given a generic class declaration

class List8742468051c85b06f0a0af9e3e506b5c{}
Here are some examples of constructed types, List8742468051c85b06f0a0af9e3e506b5c, Listbd43222e33876353aff11e13a7dc75f6 and List74c6f25e79e205a53afa93c32870c098>. A constructed type can take one or more parameters, for example List8742468051c85b06f0a0af9e3e506b5c is called an open constructed type. A constructed type that does not use type parameters, such as Listbd43222e33876353aff11e13a7dc75f6, is called a closed constructed type.

Generic types cannot be "overloaded"; that is, like ordinary types, generic types must be uniquely named within a scope.


class C{}
class Cd94943c0b4933ad8cac500132f64757f{}//Error, C is defined twice
class Cf3887e50b478d7d3734323cd28ecc8ff{}//Error, C is defined Two times
However, the type lookup rules and member access (§20.9.4) used in unqualified type name lookup (§20.9.3) do take the number of type parameters into account.

20.1.1 Type parameters

Type parameters can be provided on a class declaration. Each type parameter is a simple identifier that indicates a placeholder for the type parameters used to create a constructed type. Type parameters are formal placeholders for types that will be supplied later. In contrast, type parameters §20.5.1) are simply a proxy for the actual type when the constructed type is referenced.

type-parameter-list: (Type parameter list:)
8ca0a478262839a5decb26c938e12c8f (c67964ff536c6e1d6cb7a40d716472a0)
type-parameters: (Type parameter:)
type-parameter (type parameter)
type-parameters type-parameter (type parameter, type parameter)
type-parameter: (type parameter:)
attributesopt identifier (attribute optional identifier) ​​

Each type parameter in a class declaration defines a name in the class's declaration space (§3.3). Therefore, it cannot have the same name as another type parameter or member declared in the class. A type parameter cannot have the same name as the type itself.

The scope of type parameters in a class (§3.7), including base class, type parameter constraint statement and class body. Unlike members of a class, it does not extend to derived classes. Within its scope, a type parameter can be used as a type.

type (type):

value-type (value type)
reference-type (reference type)
type-parameter (type parameter)
Due to the type parameter Can be instantiated by many different actual type arguments, which have slightly different operations and restrictions than other types. Includes the following.

Type parameters cannot be used to directly declare a base type or interface
For member lookup rules on type parameters, if constraints exist, they depend on the constraints applied to the type parameter. See §20.7.4 for a more detailed description.



The possible conversions for a type parameter depend on the constraints (if any) applied to the type parameter. See §20.7.4 for details.
Literal null cannot be converted to the type given by the type parameter, unless the type parameter is constrained by a class constraint (§20.7.4). However, a default value expression (§20.8.1) may be used instead. Additionally, values ​​of a type given by a type parameter may be compared to null using "==" and "!=" (§20.8.4).
If the type parameters are constrained by a constructor-constraint (§20.7), the new expression can only be used with one type parameter.
Type parameters cannot be used anywhere within attributes.
Type parameters cannot be used for member access, or represent the type name of a static member or nested type (§20.9.1, §20.9.4).
In unsafe code, type parameters cannot be used as managed types (§18.2).

As a type, the type parameter is purely a compile-time construct. At run time, each type parameter is bound to the run-time type, which is specified by the type arguments provided by the generic type declaration. For this reason, at run time, the type of a variable declared with a type parameter is a closed type (§20.5.2). All statements and expressions executed at run time use type parameters of the actual type provided by that parameter as a type argument.

20.1.2 Instance type

Each class declaration has a constructed type associated with it, that is, instance type. For a generic class declaration, the instance type is formed by creating a constructed type (§20.4) from the type declaration, which uses each type argument corresponding to the type parameter. Because an instantiated type uses type parameters, it is only valid within the type parameter scope (within the class declaration). The instance type is the type of this in the class declaration. For non-generic classes, the instance type is just a declared type. Shown below are several declared classes, along with their instance types.

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

20.1.3 Base class specification

The base class specified in the class declaration may be a constructed type (§20.5). A base class itself cannot be a type parameter, but it can contain type parameters within its scope.


class Extendd94943c0b4933ad8cac500132f64757f: V{}//Error, type parameter is used as base class
Generic class declaration cannot use System.Attribute as a direct or indirect base class.

The base interface specified in a class declaration may be a constructed interface type (§20.5). The base interface itself cannot be a type parameter, but it can contain type parameters within its scope. The following code demonstrates how to implement and extend the constructed type.

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

The base interface declared by a generic type must satisfy the uniqueness rules described in §20.3.1.

Methods of a class that override or implement methods from a base class or interface must provide appropriate methods for the specific type. The code below demonstrates how the method can be overridden and implemented. This is explained further in §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 Members of generic classes

泛型类的所有成员都可以直接地或者作为构造类型的一部分,从任何封闭类(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] 这是很容易理解的,因为在运行时,不同的封闭构造类型,是属于不同的类型,比如Listbd43222e33876353aff11e13a7dc75f6 和List98c455a79ddfebb79781bff588e7b37e 这二者的实例是不能共享静态变量的。

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


Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn