Constraints on C # generic parameters

Source: Internet
Author: User

Http://birdshover.cnblogs.com/articles/392127.html

Both class and method parameters can use generics.

A constraint on a generic parameter is used to restrict the method in this generic class to the object that only the class that satisfies the constraint class can invoke.

The context keyword where is used to implement the constraint.

Multiple constraints can be applied to the same type parameter. The constraint itself can also be a generic class.

five types of generic constraints:

Constraints Describe
where t:struct The type parameter must be a value type.
where T:class Type parameter must be of type.
where T:new () The type parameter must have a public, parameterless constructor. When used in conjunction with other constraints, the new () constraint must be last.
Where T: <base class name> The type parameter must be of the specified base type or derived from the specified base type.
where T: <interface name> The type parameter must be the specified interface or the implementation of the specified interface. You can specify multiple interface constraints. Interface constraints can also be generic.

A constraint on a type parameter that increases the number of actions and methods that can be invoked. These actions and methods are supported by types in the constraint types and their derived hierarchies. Therefore, when you design a generic class or method, you need to use the constraint on the type parameter if you perform any assignment other than the generic member, or if you call a method that is not in System.Object.

Class list<t> where T:employee
{
      //...
    void add<u> (list<u> items) where U:t {...}}
}

general usage of unrestricted type parameters
Type parameters without constraints, such as public class myclass<t>{...} is called the Unrestricted type parameter (unbounded type parameters). The unrestricted type parameter has the following rules:
L cannot use operator!= and = = because the specific type parameters are not guaranteed to support these operators.
They can be converted to and from System.Object, or they can be explicitly converted to any interface type.
L can be compared with null. If an unrestricted type parameter is compared to NULL, the result of the comparison is always false when the type parameter is a value type.

No type constraint
When a generic constraint is a generic type, it is called an untyped constraint (naked type constraints). No type constraint is useful when a member method with a generic parameter is constrained to its generic parameter as the generic type of the class in which it resides.

Class list<t>
{
      //...
    void add<u> (list<u> items) where U:t {...}}
}
In the above example, the T in the context of the Add method is an untyped constraint, and the T in the context of the list class is an unrestricted type parameter.

Non-type constraints can also be used in the definition of a generic class. Note that no type constraint must also be declared in angle brackets along with other type parameters, because the compiler thinks that no type constraint is inherited from System.Object, so a generic class with no type constraints has very limited uses:

You can use an untyped constraint on a generic class when you want to force two type parameters to have an inheritance relationship.

default keyword in generic code:

One problem that arises in generic and generic methods is how to assign a default value to a parameterized type, at which point you cannot know the following two points 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 valid only if T is a reference type, and t = 0 is valid only for numeric values, not for structs. The solution to this problem is to use the default keyword, which returns null for the reference type and zero for the numeric type of the value type. For structs, it returns each member of the struct, and returns 0 or empty, depending on whether the member is a value type or a reference type. The following example of the Mylist<t> class shows how to use the default keyword. For more information, see Generics Overview.

public class mylist<t>
{
//...
Public T GetNext ()
{
T temp = default (t);
if (current!= null)
{
temp = current. Data;
Current = current. Next;
}
return temp;
}
public class mylist<t>
{
//...
Public T GetNext ()
{
T temp = default (t);
if (current!= null)
{
temp = current. Data;
Current = current. Next;
}
return temp;
}

generics in run time:

When a generic class or generic method is compiled into Microsoft intermediate Language (MSIL), the metadata it contains defines its type parameters. The MSIL used for a generic type is also different depending on whether the given type parameter is a value type or a reference type.
When the first time a generic type is constructed with a value type as a parameter, the runtime creates a specialized generic type with the supplied arguments or parameters that are replaced at the appropriate position in the MSIL. [JX3]

For example, suppose your program code is notorious for a stack consisting of an integral type, such as:

Stack<int> Stack;

At this point, the runtime replaces its type parameters with an integral type, generating adedicated version of the stack。 After that, the program code is then used toIntegral type StackWhen the runtimereusing a dedicated stack that has been created。 The following example creates an instance of two integral stacks that share a stack<int> code instance:

stack<int> Stackone = new stack<int> ();
stack<int> stacktwo = new stack<int> ();

However, if theAnother value type--such as a long integer or user-defined structure--as a parameter, create another stack elsewhere in the code, and the runtime generatesanother version of the generic type。 This time, replace the long integer with the appropriate position in the MSIL. Because each specialized generic class inherently contains a value type, no further conversions are required.

ForReference type, the work of generics is slightly different. When you first construct a generic class with any reference type, the runtime creates a specialized generic class in the MSIL, where the parameters are replaced by the object reference. Afterwhenever a constructed type is instantiated with a reference type as a parameter, its type is ignored, and the runtime multiplexing the generic class of the previously created private version。 This may be because all references are of the same size.

For example, if you have two reference types, a customer class, and an order class, further assume that you created a customer stack:

Stack<customer> customers;

At this point, the runtime generates a dedicated version of the stack for storing references to objects later, rather than storing the data. Suppose the next line of code creates a stack of another reference type named Order:

stack<order> orders = new stack<order> ();

is different from the value type, the runtimeno dedicated version of another stack is created for the order type。 Instead, the runtime creates aprivate version Stack instance, and the variable orderspoint to this instance。 If this is followed by a line of code that creates the customer type stack:

Customers = new stack<customer> ();

And a stack created with the order type previously, created theAnother instance of the private stack,And which contains thethe pointer points to a piece of memory that is the same size as the customer class。 Because the number of reference types varies widely between programs,The compiler creates only one specialized class for generic classes of reference types, so C # greatly reduces code bloat for implementations of generics.
In addition, when implementing a generic C # class with a type parameter, wondering whether it refers to a type or reference type, you can determine its true type and its type parameters at run time by reflection.

Generics in the C # underlying class library
2.0 version of. The NET Framework class library provides a new namespace, System.Collections.Generic, which contains some generic container classes and associated interfaces that are already available. And earlier versions of the. NET Framework, these classes and interfaces are more efficient and type-safe than the Non-generic container classes provided by the Before you design and implement a custom container class, consider whether to use or inherit one of the listed classes.

The table below lists the new generic classes and interfaces, next to the corresponding Non-generic classes and interfaces. In some places special attention should be paid to, for example, list<t> and dictionary<t> the behavior of the new generic class (behavior) is somewhat different and not fully compatible with the Non-generic classes they replace. For more information, refer to the System.Collections.Generic documentation:

Generic class or interface

Describe Corresponding non-generic type
Collection<t> icollection<t> To provide a base class for a generic container CollectionBase ICollection
Comparer<t> icomparer<t> icomparable<t> Compares two objects of the same generic type to be equal and sortable. Comparer IComparer IComparable
Dictionary<k, v> idictionary<k,v> Represents a collection of key/value pairs that are organized with a key. Hashtable IDictionary
Dictionary<k, V> KeyCollection Represents a collection of dictionary<k, v> keys. None.
Dictionary<k, V> ValueCollection Represents a collection of values in Dictionary<k, v>. None.
Ienumerable<t> ienumerator<t> Represents a collection that can use a foreach iteration. IEnumerable IEnumerator
Keyedcollection<t, u> Represents a collection of key values. KeyedCollection
Linkedlist<t> Represents a doubly linked list. None.
Linkedlistnode<t> Represents a node in a linkedlist<t>. None.
List<t> ilist<t> Implement the IList interface using an array of sizes that can be dynamically increased on demand ArrayList IList
Queue<t> Represents an advanced first out collection of objects. Queue
Readonlycollection<t> Provides a base class for a generic read-only container. ReadOnlyCollectionBase
Sorteddictionary<k, v> Represents a collection of key/value pairs that are sorted by keys and accessed by key to implement the Icomparer<t> interface. SortedList
Stack<t> Represents a simple LIFO collection of objects. Stack

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.