Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Avoid == and != operators on generic type parameters, but can it compare with null?

Tags:

c#

According to the Constraints on Type Parameters (C# Programming Guide) documentation it says, and I quote:

When applying the where T : class constraint, avoid the == and != operators on the type parameter because these operators will test for reference identity only, not for value equality. This is the case even if these operators are overloaded in a type that is used as an argument. The following code illustrates this point; the output is false even though the String class overloads the == operator.

With the following example:

public static void OpTest<T>(T s, T t) where T : class
{
    System.Console.WriteLine(s == t);
}
static void Main()
{
    string s1 = "target";
    System.Text.StringBuilder sb = new System.Text.StringBuilder("target");
    string s2 = sb.ToString();
    OpTest<string>(s1, s2);
}

However, ReSharper (I've just started using the demo/trial version to see if it is any worth to me) gives a hint/tip to do null-checking of parameters like so:

public Node(T type, Index2D index2D, int f, Node<T> parent)
{
    if (type == null) throw new ArgumentNullException("type");
    if (index2D == null) throw new ArgumentNullException("index2D");
    if (parent == null) throw new ArgumentNullException("parent");
}

(T is constrained with where T : class, new())

Can I safely follow ReSharper without running into problems that the C# documentation is trying to tell me to avoid?

like image 988
Daan Timmer Avatar asked Sep 25 '13 20:09

Daan Timmer


People also ask

Can a generic type be null?

This means that you can put any object in a collection because all classes in the C# programming language extend from the object base class. Also, we cannot simply return null from a generic method like in normal method.

Which of the following generic constraints restricts the generic type parameter to an object of the class?

Value type constraint If we declare the generic class using the following code then we will get a compile-time error if we try to substitute a reference type for the type parameter.

How do you indicate that a class has a generic type parameter?

A generic type is declared by specifying a type parameter in an angle brackets after a type name, e.g. TypeName<T> where T is a type parameter.

How do I compare generic types in C#?

To enable two objects of a generic type parameter to be compared, they must implement the IComparable or IComparable<T>, and/or IEquatable<T> interfaces. Both versions of IComparable define the CompareTo() method and IEquatable<T> defines the Equals() method.


2 Answers

Yes, that is fine. The documentation says not to compare two parameters because you're doing a reference comparison. The code ReSharper suggests is just ensuring the reference you've been passed is not null so that is safe to do.

In my opinion the main reason the C# docs recommend you don't do that is because if for example you do == with two strings that were passed as T1 and T2 it will do a reference comparison. Any other time you do stringA == stringB it will do a value comparison with the overload in the string class. It's really just warning against doing these types of comparisons because the operator overload that would normally be used (if you used that operator on two types declared in local scope) is not.

like image 55
evanmcdonnal Avatar answered Oct 10 '22 18:10

evanmcdonnal


Yes.

Only a very strange implementation of the == operator would make x == null mean something other than ReferenceEquals(x, null). If you are using classes that have such a strange implementation of equality, you have bigger problems than it being inconsistent when checking for null using a generic type argument.

like image 28
Eric Lippert Avatar answered Oct 10 '22 17:10

Eric Lippert