C#2.0 Specification (Generics 1)
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 List
Here are some examples of constructed types, List>. A constructed type can take one or more parameters, for example List
Generic types cannot be "overloaded"; that is, like ordinary types, generic types must be uniquely named within a scope.
class C{}
class C
class C{}//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:)
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 Extend
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] 这是很容易理解的,因为在运行时,不同的封闭构造类型,是属于不同的类型,比如List
以上就是C#2.0 Specification(泛型一)的内容,更多相关内容请关注PHP中文网(www.php.cn)!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics



Guide to Active Directory with C#. Here we discuss the introduction and how Active Directory works in C# along with the syntax and example.

Guide to C# Serialization. Here we discuss the introduction, steps of C# serialization object, working, and example respectively.

Guide to Random Number Generator in C#. Here we discuss how Random Number Generator work, concept of pseudo-random and secure numbers.

Guide to C# Data Grid View. Here we discuss the examples of how a data grid view can be loaded and exported from the SQL database or an excel file.

Guide to Patterns in C#. Here we discuss the introduction and top 3 types of Patterns in C# along with its examples and code implementation.

Guide to Prime Numbers in C#. Here we discuss the introduction and examples of prime numbers in c# along with code implementation.

Guide to Factorial in C#. Here we discuss the introduction to factorial in c# along with different examples and code implementation.

The difference between multithreading and asynchronous is that multithreading executes multiple threads at the same time, while asynchronously performs operations without blocking the current thread. Multithreading is used for compute-intensive tasks, while asynchronously is used for user interaction. The advantage of multi-threading is to improve computing performance, while the advantage of asynchronous is to not block UI threads. Choosing multithreading or asynchronous depends on the nature of the task: Computation-intensive tasks use multithreading, tasks that interact with external resources and need to keep UI responsiveness use asynchronous.
