Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does String.Equals(Object obj) check to see if this == null? [duplicate]

Possible Duplicate:
Why check this != null?

// Determines whether two strings match. 
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] 
public override bool Equals(Object obj)
{
    //this is necessary to guard against reverse-pinvokes and
    //other callers who do not use the callvirt instruction
    if (this == null)
        throw new NullReferenceException();

    String str = obj as String;
    if (str == null) 
        return false;

    if (Object.ReferenceEquals(this, obj)) 
        return true;

    return EqualsHelper(this, str);
}

The part I don't understand is the fact that it is checking for the current instance, this, against null. The comment is a bit confusing, so I was wondering what does that comment actually mean?

Can anyone give an example of how this could break if that check was not there, and does this mean that I should also place that check in my classes?

like image 735
myermian Avatar asked Apr 16 '12 05:04

myermian


People also ask

What does .equals do in C#?

In C#, Equals(String, String) is a String method. It is used to determine whether two String objects have the same value or not. Basically, it checks for equality. If both strings have the same value, it returns true otherwise returns false.

Why should NULL be on the left side in Java?

It is preferable to place string literals on the left-hand side of an equals() or equalsIgnoreCase() method call. This prevents null pointer exceptions from being raised, as a string literal can never be null by definition.


2 Answers

That check is there as a guard against native code that may invoke the function with a null this pointer. This can't happen in C#, so you don't have to put similar guards in your code. It's quite possible that the String class was written before C# was finalized and the author might have thought it important to guard against nulls, or maybe it's just common to call String methods from native code and other places that make it easy to call methods on null.

Note that even if you do manage to get called with a null this and you don't have the guard, all that will happen is that the exception will be slightly different. It might be a different exception and it might get thrown by a different member, but otherwise it's unlikely to make a difference.

In other words, if the null check wasn't there, the EqualsHelper (or one of its callees) would throw the exception rather than Equals. Since it's desirable to hide the internals of the user-visible function, it makes sense to put the check right at the beginning.

like image 169
Gabe Avatar answered Sep 20 '22 13:09

Gabe


  • Languages like C# and VB.NET use callvirt to throw NullReference before an instance method is entered (this == null) checks are not necessary.
  • Languages like F# and Managed C++ (most of the time) use the call instruction where you can get into an instance method with a null this pointer. (this == null) does have an effect.

The added null check is not only meant for the latter languages but also to aid debuggability to throw at the location where the error (call an instance method of a null object) does occur. If it were not there you can call any method inside the class without any error as long as this is never dereferences (accesses member variables). This can go so far that on your null object several method calls did work and suddenly you get a null reference exception back (the method where instance data was accessed).

If you look at the checks inside the .NET classes it is clear that only on some prominent classes like string do contain such guards. Other methods like IndexOf do not guard against this. This is inconsistent but I do think the performance penalty for such double null checks were not worth the effort because most users of the BCL are languages which uses the callvirt instruction where a second null check does not help.

like image 44
Alois Kraus Avatar answered Sep 20 '22 13:09

Alois Kraus