Connection (generic one)
This article is a Microsoft's technical article for translation. For reference for learning C #, please do not use for commercial purposes. http://msdn.microsoft.com/vcsharp/team/language/default.aspx
20.1.6 Static constructor in generic classes
The static constructor in the generic class is used to initialize the static field, perform other initialization for each different enclosed constructed type created from a particular generic class declaration. The type parameters of generic type declarations can be used in a static constructor within a static constructor.
If one of the following circumstances occurs, a new enclosure type type will be initialized first.
An instance of a closed constructor is created
Any static member of the closed structure type is quoted
In order to initialize a newly closed construct class, first set of new static fields (§20.1.5) of the particular closed type will be created. Each static field is initialized to its default value (§5.2). Next, the static field initializer (§10.4.5.1) will be executed for these static fields. The final static constructor will be executed.
Since the static constructor will execute once for each closed construct class, it will be convenient to implement the runtime check on the type parameters that cannot be checked (20.7). For example, the following type uses a static constructor to check if a type parameter is a reference type.
Class Gen
{
STATIC gen () {
IF ((Object) T.default! = null) {
Throw New ArgumentException ("Trust Be a Reference Type);
}
}
}
20.1.7 Access to protected members
In a generic category, access to the inherited protected instance members is allowed, and can be done by any type of instance constructed from the generic class. In particular, the rules for accessing the Protected and Protected INTERNAL instances specified in §3.5.3 are expanded for generic use rules.
In a generic class G, for one inherited protected instance member M, the basic expression of EM is allowed, provided that the type of E is a class type from the G constructor, or inherits to a constructor from G Class type type of class.
In an example
Class C
{
Protected T x;
}
Class D
{
STATIC void f () {
D
D
D
Dt.x = t.default;
Di.x = 123;
DS.X = "test";
}
}
The three pairs of assignment statements of X are allowed because they all occur by instances of type types constructed from generics.
20.1.8 Override in the generic class
The method, constructor, and operator can be overloaded in a generic class declaration. However, in order to avoid ambiguity in the construction class, these overloads are constrained. Two function members who use the same name declaration in the same generic class statement must have such parameter types, which is the same name and signature in the closed-constructed type. This rule contains the types where the currently does not exist in the current program, but it is still possible [1]. Type constraints on the type parameters are ignored due to the purpose of this rule.
The following example shows effective and invalid overloads based on this rule.
NTERFACE I1
Interface I2
Class G1 {
Long F1 (U U); // Invalid Overload, g
INT F1 (INT I);
Void F2 (U U1, U U2); // Effective Overload, no type parameters for u
Void F2 (INT I, STRING S); / / may be int and string at the same time
Void F3 (i1 a); // Effective Overload
Void F3 (i2 a);
Void F4 (U A); // Effective Overload
Void F4 (U [] a);
Class G2
{
Void F5 (U U, V V); // Invalid Overload, G2
Void F5 (V V, U U);
Void F6 (U U, I1
Void F6 (i1
Void F7 (U U1, I1
Void F7 (V V1, U U2);
Void F8 (REF u u); // Invalid Overload
Void F8 (OUT V V);
}
Class C1 {...}
Class C2 {...}
Class G3 Where u: c1 where v: c2
{
Void F9 (U U); // Invalid Overload, when checking overload, the constraint on U and V will be ignored
Void F9 (V V);
}
20.1.9 Parameter Array Method and Type Parameters
Type parameters can be used in the type of parameter array. For example, a given statement
Class C
{
Static void f (int x, int y, params v [] args);
Method's expansion form is called
C
C
C
Corresponding to the following form:
C
C
C
20.1.10 Override and generic classes
Functions in generic classes can rewrite the function members in the base class. If the base class is a non-extensive type or a closed constructor, then any rewrite function member cannot have a component type containing type parameters. However, if a base class is an open consignment type, the rewrite function member can use the type parameters in its declaration. When rewriting the base class member, the base class member must be determined by replacement type, as described in §20.5.4. Once a member of the base class is determined, the rules and non-float classes used for rewriting are the same.
The following example demonstrates how to work for existing generic rewrite rules.
Abstract Class C
{
Public Virtual T f () {...}
Public Virtual C
Public Virtual Void H (c
}
Class D: C
{
Public override string f () {...} // ok
Public Override C
Public override void h (c
Class E
{
Public Override u f () {...} // ok
Public Override C g () {...} // ok
Public override void h (c
}
20.1.11 Operators in generic classes
The generic category declaration can define an operator that follows the same rules as the routine class. The instance type of class declaration (§20.1.2) must be used in an operator statement in a regular rule similar to the operator, as follows
One yuan operator must accept a single parameter of an instance type. One yuan operator " " and "-" must return instance type.
One of the parameters of at least binary operators must be an instance type.
The parameter type and return type of the conversion operator must be an instance type.
The following shows an example of several effective operators in generic classes
Class x
{
Public Static x
Public static int operator * (x
Public Static Explicit Operator x
}
For a conversion operator from the source type S to the target type T, when the rule in § 10.9.3 is applied, the type parameters of any associated S or T are considered a unique type, and they have no inheritance relationship with other types, and Any constraint on these types will be ignored.
In an example
Class C
Class D
{
Public Static Implicit Operator C
Public Static Implicit Operator C
}
The first operator statement is allowed, because § 10.9.3 reasons, T and Int are considered a unique type without relationships. However, the second operator is an error because C
For a given previous example, the operator is declared for certain types of real parameters, specifying the conversion that has been presented as a predefined conversion is possible.
Struct Nullable
{
Public Static Implicit Operator Nullable
Public Static Explicit Operator T (Nullable
}
When the type Object is specified by the type of T, the second operator declares an existing conversion (from any type to Object is an implicit, or an explicit conversion).
In the case of a predefined transition between two types, any user-defined conversion on these types will be ignored. especially
If there is a predefined implicit conversion (§6.1) from type S to type T, all user-defined transformations (implicit or explicit) will be ignored.
If there is a predefined explicit conversion from type S to type T, the explicit conversion from type S to type T of Type S is ignored. But user-defined implicit conversions will still be considered.
For all types of Object, the operators declared by Nullable
Void F (INT I, NULLABLE
i = (int) n; // user-defined explicit conversion
n = i; // User-defined implicit conversion
n = (nullable
}
However, for type Object, predefined transitions hide user-defined conversions in all situations, except for one case:
Void f (Object O, Nullable
o = n; / / predefined packing conversion
o = (Object) n; / / predefined packing conversion
n = O; // User defines implicit conversion
n = (nullable
}
20.1.12 Nested type in generic class
The generic category declaration can include a nested type declaration. The type parameters of the closed class can be used in nested types. Nested type declarations can include additional type parameters, which only apply to this nested type.
Each type of statement contained in the generic class declaration is an implicit generic type declaration. When writing a reference to a type in a generic type, a constructor is included, including its type of arguments, must be named. However, in the outer class, the internal type can be used unlimited; when constructing an internal type, the example type of the outer class can be implicitly used. The following example shows the three different references to the type of constructor created from Inner, which are all correct; the first two are equivalent.
Class Outer
{
Class Inner
{
Static void f (t t, u u) {...}
}
Static void f (t t)
{
Outer
Inner
Outer
Outer.inner
}
}
Although this is a bad programming style, the type parameters in the nested type can hide a member, or a type parameter declared in the external type.
Class Outer
{
Class Inner
{
Public T t; // Reference Inner's T
}
}
20.1.13 Application Entry Point
Application entry points cannot be in a generic class declaration.
20.2 Wild Structure Statement
Like class declarations, structural declarations can have optional type parameters.
Struct-declaration: (Structure declaration :)
Attributes Opt Struct-Modifiers Opt Struct Identifier Type-Parameter-List Opt Struct-Interfaces Opt Type-Parameter-Constraints-Clauses Opt Struct-Body; OPT
(Feature Optional Structure Modifier Optional Struct Identifier Type Parameter List Optional Structure Interface Optional Type Parameter Binding Optional Structure; Optional)
In addition to the differences indicated by the structural statement in §11.3, the rules of the generic category also apply to generic structural statements.
20.3 generic interface declaration
Interface can also define an optional type parameter
Interface-Declaration: (Interface Declaration:) Attribute Opt Interface-Modifiers Opt Interface Indentifier Type-Parameter-List OPT
Interface-Base Opt Type-Parameter-Constraints-Clause Opt Interface-Body;
(Feature Optional Interface Modifier Optional Interface Identifier Type Parameter List Optional Base Conversion Optional Type Parameter Binding Optional Interface; Optional)
The interface to use the type parameter declaration is a generic interface declaration. In addition to those pointed out, generic interface declaration follows and routine structural declarations.
Each type parameter in the interface declaration defines a name in the declaration space of the interface. The scope of the type parameters on an interface includes the base interface, type binding statement, and an interface. Within its scope, a type parameter can be used as a type. The type parameters applied to the interface and the type parameters applied to the class (§20.1.1) have the same limitations.
The method in the generic interface is followed by the same overloaded rules in the generic (§20.1.8).
20.3.1 Uniqueness to implement the interface
The interface implemented by the generic type declaration must reserve uniqueness for all possible constructors. Without this rule, it will not be possible to determine the correct way to call the correct constructed type. For example, assume that a generic class declaration allows you to write as follows.
Interface I
{
Void f ();
}
Class x : i , i
{
Void i .f () {...}
Void i
}
If you are allowed to write, then the following case will not be able to determine the execution that code.
I
x.f ();
In order to determine the list of interfaces that a generic type declaration is valid, it can be performed according to the following steps.
Let L become a list of interfaces specified in the generic class, structure, or interface declaration C.
Add any base ports that have been in the L to the L
Remove any repetitive interface from L
After the type of arrameters are replaced to the L, if any possible constructive type created from C, the two interfaces in the L are the same, then the declaration of C is invalid. The constraint declaration is not considered when all possible constructive types are determined.
Above the class declaration x, the interface list L consists of I and i
20.3.2 Explicit Interface Member Realization
The explicit interface member of the constructor is used in essence is the same as the simple interface type. As in the past, the explicit interface member implementation must be limited by an interface type indicating which interface is implemented. This type may be a simple interface or constructing interface, as shown in the following example.
Interface IList
{
T [] getElement ();
}
Interface iDictionary
{
V this [k key];
Void Add (K Key, V Value);
}
Class List
{
T [] ilist
T> .THIS [int index] {...}
Void iDictionary
}