views:

486

answers:

3

Is there extra overhead in using the object.ReferenceEquals method verses using ((object)obj1 == (object)obj2)?

In the first case, there would be a static method call involved, and in both cases some form of casting to an object would be involved.

Even if the compiler balances out those methods, what about inequality?

(object)obj != null

as compared to...

!object.ReferenceEquals(obj,null)

I suppose that at some point, a logical negation would occur, either within the != operator, or as applied to the result of the ReferenceEquals method. What do you think?

There's also the issue of readability to consider. ReferenceEquals seems clearer when checking equality, but for inequality, one might miss the ! preceding object.ReferenceEquals, whereas the != in the first variation is hard to overlook.

+6  A: 

Is there extra overhead in using the object.ReferenceEquals method

No. The method directly contains the minimal IL description to perform the reference equality check (for the record: it's equivalent to VB's Is operator) and will be inlined by the JIT so there's no overhead.

About readability: I personally think that object.ReferenceEquals is potentially more readable (even in the negated form) because it explicitly expresses its semantics. The cast to object may be confusing to some programmers.

I've just found an article discussing this. It prefers (object)x == y because the IL footprint is smaller. It argues that this might facilitate inlining of method X using this comparison. However (without any detailed knowledge of the JIT but logically and intuitively) I believe this is wrong: if the JIT behaves anything like an optimizing C++ compiler, it will consider the method after inlining the call to ReferenceEquals, so (for the sake of inlining method X) the memory footprint will be exactly the same either way.

That is to say: choosing one way over the other will have no impact whatsoever on the JIT and consequently on performance.

Konrad Rudolph
+1, Agreed on readability.
JaredPar
I agree the cast to object is confusing. One may wonder why the cast in ((object)obj == null) is necessary, not realizing that reference equality ultimately boils down to (object == object). Also, comparing to null seems implicitly a reference comparison, but the typed operator is actually chosen.
Triynko
+1  A: 

The overhead of Object.ReferenceEquals is only in loading the arguments, which will be JITted away in most scenarios. After that, both Object.ReferenceEquals and operator== come down to a single IL ceq operator. At worst, the difference will be insignificant.

More importantly, Object.ReferenceEquals is much more intention-revealing than (object)o1 == (object)o2. It states clearly in the code "I am testing for reference equality / identity", rather than hiding the intent under a bunch of casts.

itowlson
I agree that the casts could be misleading, but don't you think that the '==' operator is pretty universally recognized as a reference comparison?
craig
No, on the contrary. For example, string1 == string2 performs a value comparison rather than a reference comparison. Hence the original poster's need to cast to object to force a reference comparison.
itowlson
Re your first sentence: I believe it's exactly the other way round (at least that's the way it's implemented in Rotor) but it doesn't really matter.
Konrad Rudolph
I also believe the first sentence is the other way around. The reflected c# source of ReferenceEquals is implemented as object == object. That's what led me to use (object) casting for reference equality, as I thought it might bypass the function call and be faster.
Triynko
Thanks Konrad and Triynko, you are right. I have edited the post to correct the error.
itowlson
A: 

I can't speak boldly on the overhead, I would assume that the compiler would optimize that check.

In terms of readability however, I would use the == and != operators. Anyone will immediately recognize what you're doing when they see those symbols, but with the method call it seems like it would take more effort for whoever is reading your code to say, "Oh, he's just doing a reference equality check."

Edit: Reading the other answers however, I see how the casting could potentially muck up the intention more than the method call. Perhaps it's one of those things that will remain a matter of personal preference.

craig