[Translation] The generics in C # (from DOTNET SDK 2.0 Beta1)

xiaoxiao2021-03-06  65

Source: mircrosoft.net 2.0 beta1 sdk

Translation: Jim Xu Date:

2004-11-2

Generic is a new feature of C # language 2.0 and general language runtime (CLR). The generic introduction of the concept of type parameters is introduced for .NET framework. When the type parameters make the design classes and methods, it is not necessary to determine one or more specific parameters, and the specific parameters of which can be delayed in the customer code, implementation. This means using generic type parameters T, write a class MYLIST , customer code can call: MyList , mylist or myList . This avoids the cost and risk of runtime conversion or packing operations.

table of Contents

Wan in C #. 1

I. Overview of generics. 2

Second, the advantages of generics. 5

Third, generic type parameters. 7

Fourth, the constraint of type parameters. 8

Five, generic class. 11

Sixth, generic interface. 13

Seven, generic method. 19

Eight, generic commission. 21

Nine, default keywords in generic code. 23

Ten, C templates and C # generics. 24

Eleven, the generics in runtime. 25

Twelve, generics in the basic class. 27

First, generic overview

Pan-type and generic methods and generic methods, type safety and high efficiency are not in the corresponding non-floating class and methods. Wide generics is widely used in the container and the container operation. The .NET Framework 2.0 class library provides a new namespace system.collections.Generic, which contains some new generic-based container classes. To find the sample code of the new generic container class, see generics in the underlying class library. Of course, you can also create our generic classes and methods to provide your own generalized program and design model, which is safe and efficient. The following sample code is an exemplary in a simple generic chain class class. (In most cases, it is recommended to use the List class provided by the .NET Framework class, instead of creating its own table.) Type parameter t is used in multiple places, the specific type is usually specified in these places to specify the type of elements in the table. . Type parameter T has the following usage:

l In the AddHead method, as the type of method parameters.

l In public method GetNext, as a type of return value in the DATA property of the nested Node.

l In nested classes, as the type of private member DATA.

Note that T is also effective to Node Node node. When using a specific class to implement MYLIST - such as MYLIST - each appearing T is replaced with INT.

Using system;

Using system.collections.Generic;

Public Class MyList // Type Parameter T in Angle Brackets

{

PRIVATE NODE Head;

// The Nested Type is Also Generic on T.

Private class node

{

PRIVATE NODE NEXT;

// t as private member data type:

Private t data;

// t used in non-generic constructor:

Public node (t t)

{

Next = NULL;

Data = T;

}

Public node next

{

Get {returniful

Set {next = value;}}

// t as return type of property:

Public T Data

{

Get {returntric;}

SET {data = value;}

}

}

Public mylist ()

{

HEAD = NULL;

}

// t as method parameter type:

Public void addhead (t t)

{

Node n = new node (t);

N.NEXT = HEAD;

HEAD = N;

}

Public IEnumerator getenumerator ()

{

Node current = head;

While (current! = null)

{

Yield Return Current.data;

Current = Current.next;

}

}

}

The sample code below demonstrates how the customer code uses generic class MYLIST to create an integer table. By simply changing the type of parameters, it is easy to overwrite the following code to create a table of strings or other custom types.

Class Program

{

Static void

Main

(String [] ARGS)

{

// int is the Type Argument.

MYLIST list = new mylist ();

For (int x = 0; x <10; x )

List.addhead (x);

Foreach (int i in list)

{

Console.writeLine (i);

}

Console.WriteLine ("DONE");

}

}

Second, the advantages of generics

For earlier versions of general language runtime and C # language limitations, generics provide a solution. Previous types of generalization are achieved by the type of mutual conversion of the global base class system.Object. The ArrayList container class of the .NET Framework Baseline is an example of this limitation. ArrayList is a very convenient container class, which can store any reference types or value types without changes.

// The .NET Framework 1.1 Way of Creating a list

ArrayList List1 = new arraylist ();

List1.add (3);

List1.add (105);

// ...

ArrayList List2 = new arraylist ();

List2.add ("IT IS RAINING IN

Redmond

");

List2.add ("It is snowing in the mountains);

// ...

But this convenience is cost, which requires any one of the reference types or value types to join ArrayList to SYSTEM.OBJECT. If these elements are value type, they must be packaged when they are added to the list; when retrieving them, to remove it. Type conversion and packing, unpacking operations reduce performance; in the case of an iterate large capacitor, the impact of packing and unpacking may be significant.

Another limit is a lack of time-compiled type checking, when an arraylist converts any type to Object, it cannot be used to prevent customer code like this:

ArrayList List = New ArrayList ();

// okay.

List.add (3);

// Okay, But Did you real want to do this? List.add (. "IT IS RAINING IN

Redmond

");

INT T = 0;

// this causes an invalidcastexception to be returned.

Foreach (int x in list)

{

T = X;

}

Although this is completely legitimate, and sometimes intention to create a container containing different types of elements, putting the string and int variables in an ArrayList, almost in manufacturing errors, and this error will not be discovered when it is running.

In the C # language of version 1.0 and version 1.1, you can only avoid the danger of generalized code in the container class of the .NET Framework class by writing your own specific type of container. Of course, because such classes cannot be reused by other data types, they will lose the advantages of genericity, and you must rewrite the class for each type of store.

ARRAYLIST and other similar classes truly need a way to allow customer code to specify the specific data type required before instantification. This will not be required to convert the top type to Object, and the compiler can perform type check simultaneously. In other words, ArrayList needs a type of parameters. This is precisely provided. In the generic list container in System.Collections.Generic namespace, the elements are also added to the container, similar to this:

The .NET Framework 2.0 Way of Creating A List

List list1 = new list ();

// no boxing, no casting:

List1.add (3);

// Compile-Time error:

List1.add ("IT IS Raining in

Redmond

");

Compared to ArrayList, the only List syntax in the customer code is the type parameters in declaration and instantiation. A slightly complicated return is that the table you created is not only more secure than ArrayList, but also obviously faster, especially when the elements in the table are value types.

Third, generic type parameters

In the definition of generic type or generic method, the type parameter is a placeholder, usually a capital letter, such as T. When the customer code declaration, instantiate the variable of this type, replace the Type of the data specified by the customer code. Wynhat types, such as Mylist categories given in generic overview, cannot be used as AS-IS because it is not a real type, and more like a type of blueprint. To use MYLIST , the customer code must specify a type parameter in a spare bracket to declare and instantiate a constructed type. This particular class type parameter can be any type of compiler identification. You can create any number of constructed type instances, each with different types of parameters, as follows:

MYLIST list1 = new mylist ();

MYLIST list2 = new mylist ();

MYLIST List3 = new mylist ();

In these MYLIST , each T that appears in the class will be replaced by the type parameters when running. Relying on this replacement, we only use the defined class's code, create three independent types of safe and efficient objects. For more information on CLR execution, see Waves in the run. Fourth, the constraint of type parameters

To check an element in the table to determine if it is legal or if it can be compared to other elements, then the compiler must ensure that all types of parameters that may occur in the customer code must support the operations or methods of the required calls. This guarantee is obtained by applying one or more constraints by definition of generic classes. A constraint type is a base class constraint that notifies the compiler, only this type of object or object from this type, can be used as a type parameter. Once the compiler gets this guarantee, it allows this type of method to be called in the generic class. The context key WHERE is used to achieve constraints. The following sample code illustrates the application of the base class constraint to add functions to myList class.

Public Class Employee

{

Public Class Employee

{

PRIVATE STRING NAME;

Private int ID;

Public Employee (String S, INT i)

{

Name = s;

ID = i;

}

Public String Name

{

Get {return name;}

Set {name = value;}

}

Public Int ID

{

Get {return id;}

Set {id = value;}

}

}

}

Class MyList Where T: Employee

{

// REST OF Class as Before.

Public T Findfirstoccurrence (String S)

{

T t = null;

RESET ();

While (Hasitems ())

{

IF (Current! = NULL)

{

// The constraint enables this:

IF (current.data.name == s)

{

T = Current.data;

Break;

}

Else

{

Current = Current.next;

}

} // end if

} // End while

Return T;

}

}

Constraints allow generic classes to use the EMPLOYEE.NAME attribute, because all elements of type T are an Employee object or an object inherited from EMPLOYEE.

The same type of parameters can apply multiple constraints. The constraint itself can be a generic class, as follows:

Class MyList Where T: Employee, IEMPLOYEE, IComparable , New ()

{...}

The following table lists five types of constraints:

constraint

description

Where t: struct

Type parameters must be a value type.

Where t: Class

Type parameters must be type.

Where t: new ()

Type parameters must have a public, no parametric constructor. When used in other constraints, the New () constraint must be placed in the end.

WHERE T:

Type parameters must be the specified base type or derived from the specified base type.

Where t:

Type parameters must be the specified interface or the implementation of the specified interface. You can specify a plurality of interface constraints. Interface constraints can also be generic.

The constraint of type parameters increases the number of operations and methods that can be called. These operations and methods are supported by the type of constraint and the type in its derived level. Thus, when designing a generic class or method, if the generic member executes any assignment, or the method does not in call System.Object, it is necessary to use constraints on the type parameters. General usage of unrestricted type parameters

There is no constraint type parameter, such as T in public class MyClass {...}, called unbounded type parameters. Unlimited type parameters have the following rules:

l Can't use operators! = and ==, because the specific type parameters cannot be guaranteed to support these operators.

l They can be converted to System.Object, or explicitly convert to any interface type.

l can be compared to NULL. If a non-restriction type parameter is compared with NULL, when this type of parameter is a value type, the comparison result is always false.

None type constraint

When the constraint is a generic type parameter, it is called Naked Type Constraints. When a type of type parameter is a type of parameter, it is useful to constrain its parameters to the type parameters of its class. As shown in the following example:

Class List

{

// ...

Void Add (list items) where u: t {...}

}

In the above example, t in the context of the Add method is a non-type constraint; the t in the context of the List class is a unlimited type parameter.

None type constraints can also be used in the definition of generic classes. Note that there is no type of constraint to declare in sharp brackets with other types of parameters:

// Naked Type Constraint

Public Class Myclass Where T: V

Since the compiler only believes that there is no type of constraint inherits from System.Object, the use of generic classes with non-type constraints is very limited. When you want to force two types of parameters to have inheritance relationships, there is no type of constraints for generic classes.

Five, generic class

The generic classes encapsulates the operations that are not for any particular data type. Generic classes are often used in containers, such as linkers, hash tables, stacks, queues, trees, and so on. The operations in these classes, such as adding, deleting elements, regardless of the type of data stored, performs almost the same operation.

For most cases, it is recommended to use the container classes provided in the .NET Framework 2.0 class. For more information on using these classes, see generics in the underlying class library.

Typically, a generic class is created from an existing concrete class and a type changed to a type parameter each time until the best balance of general and usability. When you create your own generic class, you need to focus on things:

l What types of types should be generic as type parameters. The general rules are, the more the types represented by parameters, the greater the flexibility and reuse of the code. Excessive generalization can cause code to be understood by other developers.

l If there is constraint, then the type parameters need to be constrained. A good habit is to use the largest constraint as much as possible while ensuring that all types that need to be processed can be processed. For example, if you know that your generic class is intended to use the reference type, then apply this class's constraint. This prevents unintentional use value, while using an AS operator to T, and check the air reference.

l Placing generics in the base class or in subclasses. The generic class can be a base class. This should also be considered in the design of the same non-flora. Inheritance rules for generic base classes.

l Whether to implement one or more generic interfaces. For example, to design a class that creates an element in a generic-based container, you may need to implement an interface similar to ICOMPARABLE , where t is the parameter of this class. An example of a simple generic class in a generic summary.

Rules for type parameters and constraints have some potential impact on generic behavior (Behavior), especially for inheritance and member accessibility. It is important to understand some terms before explaining this problem. For a generic class Node , the customer code can create a closed construct type (Node ), or the type parameter is not specified, such as designating a generic base class to create an open Construction type (Node ). Pan types can inherit from specific classes, closed construction types or open constructive types:

// Concrete Type

Class Node : BaseNode

// Closed Constructed Type

Class Node : BaseNode

// Open Constructed Type

Class Node : BaseNode

The non-floating specific classes can inherit self-enclosed construction base, but cannot inherit from open construction base classes. This is because the customer code cannot provide the type parameters required by the base class.

// No error.

Class Node: BaseNode

// generates an error.

Class Node: BaseNode

The generic specific class can inherit the type of self-opening structure. In addition to the type parameters shared with the subclass, the type must be specified for all type parameters, as shown in the following code:

// generates an error.

Class Node : BaseNode {...}

// okay.

Class Node : BaseNode {...}

Inherit the generic class of the open structure type, must be specified:

Generic Classes That Inherit from Open Constructed Types Must Specify Must Specify Constraints That Are A SuperSet of, or Imply, The Constraints on The Base Type:

Class NodeItem Where T: iComparable , new () {...}

Class MyNodeItem : NodeItem Where T: iComparable , New () {...}

The generic type can use multiple types of parameters and constraints, as follows:

Class Keytype {...}

Class SuperkeyType Where u: iComparable , where v: new () {...}

Open structure and enclosed construct Types can be used as parameters:

Void SWAP (List List1, List List2) {...}

Void swap (list list1, list list2) {...}

Six, generic interface

Whether it is a generic container, it is also useful to define the extension of the generic class in the container. Combining generic interfaces with generic classes is better usage, such as ICOMPARABLE rather than iComparable to avoid packing and unpacking operations on the value type. The .NET Framework 2.0 class library defines several new generic interfaces to match the usage of new containers in System.Collections.Generic. When an interface is specified as a constraint of the type parameter, only the type of the interface can be used as the type parameters. The following sample code shows a SortedList class derived from MyList . For more information, see the outline of generics. SortedList Added constraint where t: iComparable .

This allows the Bubblesort method in sortedlist to use the iComparable .compareto method of the elements in the table. In this example, the elements in the table are simple classes - the Person class that implements iComparable .

Using system;

Using system.collections.Generic;

// Type Parameter T IN Angle Brackets.

Public Class MyList

{

Protected node head;

protected node current = null;

// Nested Type is Also Generic on T

Protected Class Node

{

Public node next;

// t as private member datattype.

Private t data;

// t used in non-generic constructor.

Public node (t t)

{

Next = NULL;

Data = T;

}

Public node next

{

Get {returniful

Set {next = value;}

}

// t as return type of profment.

Public T Data

{

Get {returntric;}

SET {data = value;}

}

}

Public mylist ()

{

HEAD = NULL;

}

// t as method parameter type.

Public void addhead (t t)

{

Node n = new node (t);

N.NEXT = HEAD;

HEAD = N;

}

// Implement IEnumerator To Enable Foreach

// ortho orthot there. Note That In C # 2.0

// you are not required and import current and

// GetNext. The compiler does That for you.

Public IEnumerator getenumerator ()

{

Node current = head;

While (current! = null)

{

Yield Return Current.data;

Current = Current.next;

}

}

}

Public Class SortedList : MyList Where T: iComparable

{

// a Simple, Unoptimized Sort Algorithm That // Orders List Elements from Lowest to Highest:

Public void bubblesort ()

{

IF (null == head || null == head.next)

Return;

BOOL swapped;

DO

{

Node previous = null;

Node current = head;

Swapped = false;

While (current.next! = null)

{

// Because We need to call this method, The sortedlist

// Class Is Constrained On IEnumerable

IF (current.data.compareto (current.next.data)> 0)

{

Node TMP = Current.next;

Current.next = current.next.next;

TMP.NEXT = CURRENT;

IF (previous == NULL)

{

HEAD = TMP;

}

Else

{

Previous.Next = TMP;

}

Previous = TMP;

Swapped = true;

}

Else

{

Previous = CURRENT;

Current = Current.next;

}

} // End while

WHILE (SWAPPED);

}

}

// a Simple Class That IMPLEments ICOMPARABLE

// using itself as the type argument. this is a

// Common Design Pattern in Objects That Are

// stored in Generic Lists.

Public Class Person: iComparable

{

String name;

Int agec;

Public Person (String S, INT I)

{

Name = s;

AGE = I;

}

// this Will Cause List Elements

// to be sorted on age values.

Public int COMPARETO (Person P)

{

RETURN AGE - P.AGE;

}

Public override string toString ()

{

Return Name ":" AGE;

}

// Must Implement Equals.

Public Bool Equals (Person P)

{

Return (this.Age == P.AGE);

}

}

Class Program

{

Static void

Main

(String [] ARGS)

{

// Declare and instantiate a new generic sortedlist class.

// Person is the Type Argument.

SortedList list = new sortedlist ();

// CREATE NAME AND AGE VALUES TO INITIALIZE PERSON Objects.

String [] Names = new string [] {"Franscoise", "Bill", "Li", "Sandra", "Gunnar", "Alok", "Hiroyuki", "Maria", "Alessandro", "Raul"} ; int [] AGES = New int [] {45, 19, 28, 23, 18, 9, 108, 72, 30, 35};

// Populate the list.

For (int x = 0; x <10; x )

{

List.addhead (New Person (Names [x], Ages [x]));

}

// Print Out UNSORTED LIST.

Foreach (Person P in List)

{

Console.writeline (p.toString ());

}

// sort the list.

List.bubblesort ();

// Print Out Sorted List.

Foreach (Person P in List)

{

Console.writeline (p.toString ());

}

Console.WriteLine ("DONE");

}

}

You can specify multiple interfaces as constraints in one type:

Class Stack Where T: iComparable , iMystack1 {}

An interface can define multiple types of parameters as follows:

IDictionary

The inheritance rules for interfaces and classes are the same:

// okay.

ImyInterface: ibaseinterface

// okay.

ImyInterface : ibaseinterface

// okay.

ImyInterface : ibaseinterface

// Error.

ImyInterface : ibaseinterface2

The specific class can realize the closed construction interface, as follows:

Class myclass: ibaseinterface

The generic class can achieve generic interface or enclosed construct interface, as long as the class's parameter list provides all the parameters required for the interface, as follows:

// okay.

Class myclass : ibaseinterface

// okay.

Class Myclass : IBaseInterface

Frequency class, generic structure, generic interfaces have rules that are also overloaded. For more information, see the generic method.

Seven, generic method

The generic method is a method of claiming type parameters, as follows:

Void Swap (Ref T LHS, REF T RHS)

{

T Temp;

Temp = LHS;

LHS = rhs;

RHS = TEMP;

}

The following sample code shows an example of calling a method with INT as a type of parameters:

INT A = 1;

INT b = 2;

// ...

SWAP (a, b);

You can also ignore type parameters, and the compiler will inibreter of it. The following is called the SWAP code and the above example is equivalent:

SWAP (A, B);

Static methods and example methods have the same type inference rules. The compiler can infer the type parameters based on the incoming method parameters; and cannot be judged according to constraints or return values. Therefore, the type inference is invalid for the method without parameters. Type Inference When compiled, and before the compiler parses the overload method flag. The compiler application type inference logic for all the generic methods of all the same name. In the stage of decision (Resolution), the compiler contains only generic classes that have been submitted successful. For more information, see C # 2.0 Specifications, 20.6.4

Type parameter infer

In generic methods, the non-extensive method can access the type parameters in the class, as follows:

Class myclass

{

// ...

Void Swap (Ref T LHS, REF T rHS) {...}

}

You cannot [JX1] define a generic method, and its class has the same type of parameters; trying to do so, the compiler will generate a warning CS0693.

Class MyList

{

// cs0693

Void mymethod {...}

}

Class MyList

{

// this is okay, but not common.

Void SomeMethod () {...}

}

Use constraints can use more types of parameters in the method. This version of SWAP is called SwapifGreater , which can only use the type parameters that implements IComparable .

Void Swapifreater (Ref T LHS, Ref T RHS) Where T: iComparable

{

T Temp;

IF (lhs.comPareto (RHS)> 0)

{

Temp = LHS;

LHS = rhs;

RHS = TEMP;

}

}

The generic method is overloaded by multiple type parameters. For example, the following methods can be placed in the same class:

Void Dosomething () {}

Void Dosomething () {}

Void Dosomething () {}

Eight, generic commission

Whether in the class definition or outside the class definition, the commission can define its own type parameters. The code that references generic commission can specify type parameters to create a closed constructed type, which is the same as instantiating generic classes or calling generic methods, as shown in the following example:

Public Delegate Void MyDelegate (T Item);

Public Void Notify (INT I) {}

// ...

MyDelegate m = new mydlegate ;

C # 2.0 has a new feature called method group conversion, specific agent and generic agent types can be used. Method group conversion can write the above line to simplify the grammaxial:

MyDelegate m = notify;

The type parameters of generic classes can be used in the same way as the classes of the generic classes.

Class Stack

{

T [] items;

Int index

// ...

Public Delegate Void StackDelegate (t [] items);

}

Quote the entrusted code must specify the type parameters of the class, as follows:

Stack s = new stack ();

Stack .stackDelegate myden = stacknotify; generic commission is especially useful when defining events based on typical design patterns. Because Sender has a strong type [JX2], no longer uses Object to convert each other.

Public void stackeventhandler (t sender, u Eventargs);

Class Stack

{

// ...

Public Class Stackeventargs: Eventargs {...}

Public Event Stackeventhandler , stackeventargs> stackevent;

Protected Virtual Void OnstackChanged (Stackeventargs A)

{

Stackevent (this, a);

}

}

Class myclass

{

Public Static Void HandleStackChange (Stack stack, stackeventargs args) {...};

}

Stack S = New Stack ();

Myclass mc = new myclass ();

S.stackeventhandler = mc.handlestackchange;

Nine, default keywords in generic code

One problem in generic and generic methods is how to assume the default value to the parameterization type, at which point the following two points cannot be known in advance:

L T will be a value type or a reference type

l If t is a value type, then T will be numeric or structure

For a variable T of a parameterized type T, the T = NULL statement is legal only when T is a reference type; T = 0 is only valid for the value, and the structure is not. The solution to this problem is to use the default keyword, which returns to the reference type, and returns zero the value of the value type. For the structure, it will return to the structure each member, and the value is the value type or the reference type, returns zero or empty. The following MYLIST example shows how to use the Default keyword. For more information, see the outline of generics.

Public Class MyList

{

// ...

Public t getnext ()

{

T Temp = Default (T);

IF (Current! = NULL)

{

Temp = current.data;

Current = Current.next;

}

Return Temp;

}

}

Ten, C templates and C # generics

(Not translated)

C # Generics and C templates are both language features that provide support for parameterized types. However, there are many differences between the two. At the syntax level, C # generics are a simpler approach to parameterized types without the complexity of C templates. In addition, C # does not attempt to provide all of the functionality that C templates provide. At the implementation level, the primary difference is that C # generic type substitutions are performed at runtime and generic type information is thereby preserved for instantiated objects. for more information, see Generics In The Runtime.The Folllowing Aren C # generics and C Templates:

· C # generics do not provide the Same Amount of Flexibility AS C Templates. For Example, IT IS Not Possible To Call Arithmetic Operators In A C # generic class, although it is possible to call user defined Operators.

· C # Does Not Allow Non-Type Template Parameters, SUCH AS Template C {}.

· C # does not support evicit specialization; That IS, A Custom IMPLEMENTATION OF A TEMPLATE for A Specific Type.

· C # Does Not Support Partial Specialization: a Custom IMplement for A Subset of The Type Arguments.

· C # does not allow the Type Parameter to be used as the base class for the generiic type.

· C # does not allow type parameters to have default types.

· In C #, a Generic Type Parameter Cannot Itself becomter, Although Constructed Types Can Be Used As Generals. C Does Allow Template Parameters.

· C allows code that might not be valid for all type parameters in the template, which is then checked for the specific type used as the type parameter. C # requires code in a class to be written in such a way that it will work with any type that satisfies the constraints For example, in C it is possible to write a function that uses the arithmetic operators and -. on objects of the type parameter, which will produce an error at the time of instantiation of the template with a type that Does Not Support these Operators. C # disallows this; The only language constructs allowed area Those That Can Be Deduced from the constraints. Eleven, running in runtime

Specialized Generic Types Are Created ONCE for Each Unique Value Type Used as a parameter.

When the generic class or generic method is compiled as a Microsoft Intermediate Language (MSIL), the metadata it contains defines its type parameters. The MSIL used for generic types is also different depending on the type parameters given.

When a generic type is constructed as a parameter as a parameter, a dedicated generic type is created using the parameters provided by the provided parameters or the appropriate position in MSIL. The runtime will create a dedicated generic type for each unique value of the parameter. [Jx3]

For example, suppose your program code is called a stack consisting of integer, such as:

Stack stack;

At this point, it is used to properly replace its type parameters properly, generate a dedicated version of the stack. Thereafter, the program code is used to run the dedicated stack that has been created when the program code is used. The following example creates an instance of two integer stacks, which share a Stack code instance:

Stack stackne = new stack ();

Stack stacktwo = new stack ();

However, if another value type-as a long-integrated or user-defined structure-as a parameter, another stack is created in other parts of the code, then another version of the generic type is generated. This time is the appropriate location for the long integer to MSIL. Since each dedicated generic class contains value type, no reproduction is required.

For reference types, generic work is slightly different. When the generic class is constructed for the first time, a dedicated generic class is created in MSIL at runtime, where the parameters are replaced by the object reference. Thereafter, whenever a reference type is used as a parameter to instantiate a constructed type, it is ignored that its type and the generic class of previously created dedicated versions are used. This may be due to the same size of all references.

For example, if you have two reference types, a Customer class and an Order class; further assume that you have created a Customer's stack:

Stack Customers;

At this time, a dedicated version of the stack is generated at runtime, which is used to store references to the object, not the stored data. If the next line of code creates a stack of another reference type, named ORDER:

Stack ORDERS = New Stack ();

Unlike the value type, the runtime does not create a dedicated version of the ORDER type. Instead, a dedicated version stack instance is created at runtime, and the variable order is point to this instance. If it is the code that is a stack of Customer type:

Customers = New Stack ();

As previously created by the Order Type, another instance of a dedicated stack is created, and the pointers included in the pointer points to memory consistent with the Customer class. Since the quantity of different programs quote is large, the compiler only creates a special class only for the general type of the reference type, so the C # is greatly reduced to the utility of genericity reduces the code expansion.

In addition, when using the type parameters to implement a generic C # class, you want to know that it is a type or a reference type, which can determine its true type and its type parameters by reflecting at runtime.

Twelve, generics in the basic class library

The 2.0 version of the .NET Framework class library provides a new namespace, System.Collections.Gener, which contains some generic container classes and related interfaces that have been used. These classes and interfaces are more efficient and type safe than the non-float containers provided by the earlier version .NET framework. Before designing, you can implement a custom container class, please consider whether or not one of the listed classes is used.

The following table lists new generic classes and interfaces, next to the corresponding non-flood type and interface. Pay special attention to some places, such as List and Dictionary , the behavior of the new class (Behavior) is somewhat different from the non-extensive classes replaced, nor is it compatible. For more detailed content, please refer to System.Collections.Generic documentation

Wild class or interface

description

Corresponding non-extensive type

Collection

Icollection

Provide base classes for generic containers

CollectionBase

ICollection

Comparer

IComparer

IComparable

Compares whether the objects of the two same generic types are equal, can be sorted.

Comparer

Icomparer

Icomparable

Dictionary

IDictionary

Indicates the key / value of the key to organize.

Hashtable

IDictionary

Dictionary .keycollection

Represents a collection of Dictionary .

NONE.

Dictionary .ValueCollection

Represents a collection of Dictionary mediative.

NONE.

Ienumerable

Ienumerator

Indicates a collection of foreach iterations.

Ienumerable

Ienumerator

KeyedCollection

Indicates a collection of key values.

KeyedCollection

LinkedList

Represents a two-way linked list.

NONE.

LinkedListNode

Indicates the node in LinkedList .

NONE.

List

IList Using the size of the ILIST interface with an array of updated dynamically

ArrayList

IList

Queue

Represents the advanced first set of objects.

Queue

ReadonlyCollection

Provide base classes for generic read-only containers.

ReadonlyCollectionBase

SortedDictionary

Indicates a collection of key / value pairs, these keys and values ​​button routine and can be accessed according to the key to implement the IComparer interface.

Sortedlist

Stack

A simple backward process that represents an object.

Stack

转载请注明原文地址:https://www.9cbs.com/read-89677.html

New Post(0)