Pan in C # (from DotNet SDK 2.0 Beta1) Reposted: SNOW Date: 2004-11-25 Popularity: 177 Wildered 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. The generics in the catalog C # 1, outlines. 2 II, generic advantages. 5 third, generic type parameters. 74. Constraints of type parameters. 8 5. Wizard. 116, generic Interface. 137, generic method. 198, generic commission. 219, default keywords in generic code. 23 Ten, C templates and C # generic differences. 24 Eleven, generics in runtime 25 12. Popularity in the basic class. 27, generic outline generic classes and generic methods, types, type safety and efficiency, is the corresponding non-floatic class and The method is not. 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; // Type: Private T Data; // T Used in non-generic constructor: public node (t t) {next = null; data = t;} public node next {get {return next;} set {NEXT;} set {recaNNEXT = Value;}} // t as return type} set {data = value;}}} public mylist ()}} public mylist ()}} public mylist ()}} public mylist ()}} public : public void addhead (t) {node n = new node (t); n.next = head; head = n;} public} public} PUBLIC IENUMERATOR getEnumerator () {node current = head; while (current! = null) {Yield Return Current.data; CURRENT = CURRENT.NEXT;}}} The following sample code 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 (); for (int x = 0; x <10; x ) list. Addhead (x); Foreach (INT i in list) {console.writeline (i);} console.writeline ("done");}} II, generic advantages for early versions of generic language running and C # language Limitation, 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.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, this requires any reference type to join ArrayList Or the value type is implicitly converted up 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 the 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 legal, and sometimes it is intentional to create a container containing different types of elements, but put the string and int variables in an arraylist, almost in manufacturing errors, and this It will be discovered when it is running until 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 < INT> (); // no boxing, no cast: list1.add (3); // compile-time error: list1.add ("it is raining in redmond."); compared with ArrayList, in customer code The only increased list syntax is the type parameters in declarations 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 definition of generic types or generic methods, type parameters are 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 using different types of parameters, as follows: MYList list1 = new mylist (); mylist list2 = new mylist (); MYLIST < SomeStruct> 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 guarantee that all types of parameters that may occur in the customer code must support the required Calling operation or method. 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;} 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.data == s) {t = current.data; Break; } else {current = current.next;}} // end if}}}}}}} The constraint allows generic classes to use the EMPLOYE.NAME attribute, because all the elements of type T are an EMPLOYEE object Or an object that inherits from EMPLOYEE. The same type of parameters can apply multiple constraints. The constraint itself can also be a generic class, as follows: Class MyList Where t: Employee, IEMPLOYE, ICOMPARABLE , new () {...} The following table lists five types of constraints: Constraint Description Where T: struct Type The parameter must be a value type. WHERE T: Class type parameters must be type. WHERE T: New () type parameter 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. The general usage of unrestricted type parameters is not constrained type parameters, such as T in public class myclass {...}, known as unbounded type parameters. Unlimited type parameters have the following rules: L cannot 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. There is no type of constraint when 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, It 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 constraints must be declared in sharp brackets with other types of parameters: // Naked Type Constraint Public Class MyClass WHERE T: V Because the compiler only believes that there is no type of constraint from System. Object inherits, so 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. 5. The generic type generic classes encapsulates 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 the matter: l which 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 ). Pancases can inherit from specific classes, closed construction types or open constructive types: // Concrete Type Class Node : BaseNode // Closed Constructed Type Class Node : BaseNode // Open Construction Type Class Node : BaseNode The specific class of non-floats 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 specific class of generics can inherit self-opening constructive. 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 {...} Inherited the generic class of the open structure type, must be specified: generic classes That Inherit from Open Constructed Types Must Specify Must Specify Constees 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 () {...} Types can use multiple types of parameters and constraints, as follows: Class KeyType {...} Class Superkeytype where u: iComparable , where v: new () {...} Open Structure and closed construction types can be used as a method of parameters: Void Swap (List List1, List List2) {...} void swap (list list1, list list2) { ...} 6. The generic interface is a generic class of the generic container or a generic class of the elements in the container, which is useful. 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 met; // t used in non-generic constructor. Public node (t t) {next = null; data = t;} public node next {get {return next; } set {next = value;}} // t as return type}} set {data = value;}}} public mylist ()}} public mylist ()}} public mylist ()}} public} AsMETHOD Parameter Type. Public Void Addhead (T T) {node n = new node (t); n.next = head; head = n;} // Implement IEnumerator to enable foreach // orthoteur list. note that in C # 2.0 // you are not required to implment 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;}}} Publi C Class SortedList : MyList Where T: iComparable {// A Simple, Unoptimized Sort Algorithm That // ORDERS LIST Elements from Lowest to Highest: Public Void Bubblesort () {== = = ha || 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 omenumerable 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 }wide (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 age.. 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 int 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 ("DONE");}} can specify multiple interfaces in one type Constraint, as follows: Class Stack <
T> Where t: iComparable , IMYSTACK1 {} An interface can define multiple type parameters, as follows: iDictionary interface and class inheritance rules are the same: // okay. Imyinterface: ibaseinterface // okay. ImyInterface // okay. Imyinterface : ibaseinterface // error. Imyinterface : ibaseinterface2 The specific class can enclose the closed construction interface, As follows: Class MyClass: ibaseinterface Wizard types You can implement generic interfaces or enclosed constructors, as long as the class's parameter list provides all parameters required by the interface, as follows: // okay. Class myclass : ibaseinterface // okay. Class Myclass : IBaseInterface generic class, generic structure, generic interface has the same method overloaded rules. For more information, see the generic method. Seven, generic method 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 sample code shows an example of invoking the method as a type parameter: int a = 1; int b = 2; // ... swap (a, b); can also ignore type parameters, compiler I will inform it. The code of SWAP is called with the above example is equivalent: SWAP (A, B); the static method and example method have the same type of inferred rule. 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 specification, 20.6.4 Type Parameters Inference In generic methods, non-float methods can access the type parameters in the class, as follows: Class MyClass {// ... Void Swap (Ref T LHS, REF T rHS) {...}} cannot be [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 swapifgreater (REF T LHS, REF T r HS) 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 commissioning, either in class definition In addition to 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 construction 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 mydelegate ; C # 2.0 has a new feature called method group conversion, specific agent and generos The type of agent can be used. Method group conversion can write the above line to make a simplified grammax: MyDelegate m = notify; delegate defined in the generic class, the type parameters of the generic class can be used in the same way as the class. Class Stack {T [] Items; int index // ... public delegate void stackdelegate (t [] items);} Reference The 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; 9. The default keyword in generic code is a problem in generic classes and generic methods. 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 the value type or the reference type l If T is the value type, then T will be a value or structure for a parameterized Type t Variable T, when T is a reference type, T = NULL statement is legal; 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 difference (untranslated) 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 following are the key differences between 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 Arithmet . Ic 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 explicit specialization.;
that is, a custom implementation of a template for a specific type · C # does not support partial specialization:.. a custom implementation for a subset of the type arguments · C # does not allow the type parameter to be used as the base class for the generic type. · C # does not allow type parameters to have default types. · In C #, a generic type parameter can not itself be a generic, although constructed types can be used as generics. 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 operato . Rs C # disallows this; the only language constructs allowed are those that can be deduced from the constraints XI generic Specialized generic types of runtime are created once for each unique value type used as a parameter when the generic class. Or the generic method is compiled into 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 named a stack consisting of integer, such as: stack stack; at this time, running with integer with its type parameters, generate a special 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 two instances of integer stack, which share a Stack code instance: stack stackne = new stack (); stack stacktwo = new stack () However, if another value is created, another stack is created in other parts of the code, such as a parameter, such as a long set or user-defined structure, then generates another version of the generic type. 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 a Order class; further assume that you have created a custom's stack: Stack Customers; at this time, a dedicated version of the stack is generated while running, for later Store references for objects, not stored data. If the next line of code creates a stack of another reference type, named Order: Stack ORDERS = New Stack (); and the value type is different, it is not to create another stack for the Order type when runtime. Special version. Instead, a dedicated version stack instance is created at runtime, and the variable order is point to this instance. If you are a line of creating a stack of Customer type: Customers = new stack ();, the other example of the dedicated stack is created, and the pointer to the pointer points to a size. Memory consistent with 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, the generic version 2.0 of the basic 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.