Constraints on Type Parameters (C# Programming Guide)
Visual Studio 2005
Other versions
When defining a generic class, you can Places restrictions on the kinds of types that client code can use for type parameters when instantiating a class. If client code attempts to instantiate a class using a type that is not allowed by a constraint, a compile-time error occurs. These limits are called constraints. Constraints are specified using the where context keyword. The following table lists the six types of constraints:
Constraint | Description |
---|---|
T : Structure |
type parameters must be value types. Any value type except Nullable can be specified. For more information, see Using Nullable Types (C# Programming Guide). |
T: Class |
Type parameters must be reference types, including any class, interface, delegate, or array type. |
T: new() |
Type parameters must have a parameterless public constructor. When used with other constraints, the new() constraint must be specified last. |
T: |
The type parameter must be the specified base class or derived from The specified base class. |
T: |
Type parameters must be the specified interface or implement the specified interface. Multiple interface constraints can be specified. Constraint interfaces can also be generic. |
T: U |
Type parameters provided for T must be parameters provided for U or derived from U parameters provided. This is called a naked type constraint. |
Reasons for using constraints
If you want to check an item in a generic list to determine if it is valid, or compare it to some other item To make a comparison, the compiler must provide some assurance that the operator or method it needs to call will be supported by any type parameters that the client code may specify. This guarantee is obtained by applying one or more constraints to the generic class definition. For example, a base class constraint tells the compiler that only objects of this type or objects derived from this type can be used as type parameters. Once the compiler has this guarantee, it can allow calling methods of that type in a generic class. Constraints are applied using the context keyword where. The following code example demonstrates how to add base class constraints to the GenericList
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; } } } public class GenericList<T> where T : Employee { private class Node { private Node next; private T data; public Node(T t) { next = null; data = t; } public Node Next { get { return next; } set { next = value; } } public T Data { get { return data; } set { data = value; } } } private Node head; public GenericList() //constructor { head = null; } public void AddHead(T t) { Node n = new Node(t); n.Next = head; head = n; } public IEnumerator<T> GetEnumerator() { Node current = head; while (current != null) { yield return current.Data; current = current.Next; } } public T FindFirstOccurrence(string s) { Node current = head; T t = null; while (current != null) { //The constraint enables access to the Name property. if (current.Data.Name == s) { t = current.Data; break; } else { current = current.Next; } } return t; } }
With constraint type parameters, you can increase the number of allowed operations and method calls supported by the constraint type and all types in its inheritance hierarchy. Therefore, when designing a generic class or method, if you want to do anything other than simple assignment to a generic member or call any method that is not supported by System.Object , you will need the type parameter Apply constraints.
When applying the where T : class constraint, it is recommended not to use the == and != operators on type parameters. Because these operators only test reference identity and not value equality. This is true even if these operators are overloaded in the type used as a parameter. The code below illustrates this; even though the String class overloads the == operator, the output is false.
C
#public static void OpTest<T>(T s, T t) where T : class { System.Console.WriteLine(s == t); } static void Main() { string s1 = "foo"; System.Text.StringBuilder sb = new System.Text.StringBuilder("foo"); string s2 = sb.ToString(); OpTest<string>(s1, s2); }
The reason for this is that the compiler only knows at compile time that T is a reference type, so it must use the default operator that is valid for all reference types. If you need to test value equality, the recommended approach is to both apply the where T : IComparable
Unbound type parameters
Unbound type parameters (such as public class SampleClass< The T in T>{}) is called an unbound type parameter. Unbound type parameters have the following rules:
You cannot use the != and == operators because there is no guarantee of a concrete type parameter These operators are supported.
You can convert them to and from System.Object or explicitly convert them to any interface type.
They can be compared to null . When comparing an unbound parameter to null , the comparison will always return false if the type parameter is a value type.
Naked type constraints
Generic type parameters used as constraints are called naked Type constraints. Naked type constraints are useful when a member function that has its own type parameter needs to constrain that parameter to a type parameter of the containing type, as in the following example:
C
class List<T> { void Add<U>(List<U> items) where U : T {/*...*/} }
In the above example, T is a naked type constraint in the context of the Add method, and an unbound type constraint in the context of the List class certain type parameters.
Naked type constraints can also be used in generic class definitions. Note that the naked type constraint must also have been declared in angle brackets with any other type parameters:
C# //naked type constraint public class SampleClass<T, U, V> where T : V { }
The role of naked type constraints on generic classes is very limited, because the compiler assumes nothing more than a certain naked type constraint No assumptions are made other than derived from System.Object. You can use naked type constraints on a generic class when you want to enforce an inheritance relationship between two type parameters.
The above is the graphic and text details of where type constraints in C#. For more related content, please pay attention to the PHP Chinese website (www.php.cn)!