Generics


Ex:

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);
}

Output: false
why?

Reason:

When applying constraint "where T : class"; it is recommended that you do not use "==" and "!=" operators on the type parameters. These operators will test reference identity only, not for value equalitty.
Here even if these operators are overloaded in a type used as an argument; yet the output is false (even though string class overloads the "==" operator.

The reason for this behavior is that, at compile time, the compiler only knows that T is a reference type, and therefore must use the default operators that are valid for all reference types. If you need to test for value equality, the recommended way is to also apply the where T : IComparable<T> constraint and implement that interface in any class that will be used to construct the generic class.


Unbounded Type Parameter:
Type parameters that have no constraints, such as T in public class SampleClass<T>{}, are called unbounded type parameters. Unbounded type parameters have the following rules:
  • The != and == operators cannot be used because there is no guarantee that the concrete type argument will support these operators.
  • They can be converted to and from System.Object or explicitly converted to any interface type.
  • You can compare to null. If an unbounded parameter is compared to null, the comparison will always return false if the type argument is a value type.
Naked Type Constraints:
When a generic type parameter is used as a constraint, it is called a naked type constraint.

- Naked type constraints are useful when a member function with its own type parameter needs to constrain that parameter to the type parameter of the containing type.
- Naked type constraints can also be used in generic class definitions.
- Naked type constraint must also have been declared within the angle brackets along with any other type parameters.

Example:
class List<T>
{
    void Add<U>(List<U> items) where U : T {/*...*/}
}
T is a naked type constraint in the context of the Add method, and an unbounded type parameter in the context of the List class

//naked type constraint
public class SampleClass<T, U, V> where T : V { }

- Compiler can assume nothing about a naked type constraint except that it derives from System.Object. Use naked type constraints on generic classes in scenarios in which you wish to enforce an inheritance relationship between two type parameters.

No comments:

Post a Comment