Explicitly cast a string to an object before testing if null

  • Thread starter Thread starter GlennDoten
  • Start date Start date
G

GlennDoten

I just happened to be looking through the implementation of the
System.Version class in the SSCLI and one of the constructors starts
like this:

public Version(String version) {
if ((Object) version == null)
throw new ArgumentNullException("version");

Does anyone have any ideas why the string parameter is being cast to an
object prior to checking for null? Is there some circumstance where not
having the explicit cast to object would cause the test for null to not
work as expected?
 
I just happened to be looking through the implementation of the
System.Version class in the SSCLI and one of the constructors starts
like this:

public Version(String version) {
if ((Object) version == null)
throw new ArgumentNullException("version");

Does anyone have any ideas why the string parameter is being cast to an
object prior to checking for null? Is there some circumstance where not
having the explicit cast to object would cause the test for null to not
work as expected?

Yes -- if the object in question is of a type that overrides
operator== and does funny things when comparing to a null reference.
However, such an implementation would be considered defective by any
standard and should be fixed rather than worked around!

But in fact, it's a good idea to cast to object before comparing to
null whenever operator== is overriden by the compared type, even if it
doesn't do funny things. The reason is that it's much faster.

When applied to System.Object the "==" and "!=" tokens directly
translate to a single IL instruction each. But when applied to a type
that overrides operator== method calls are generated instead.

I suspect it's for this latter reason that the object cast exists.
System.String does override operator== to achieve "value type
semantics", as they call it; i.e. two strings are equal if they have
the same contents. The object cast saves a method call.
 
Christoph said:
Yes -- if the object in question is of a type that overrides
operator== and does funny things when comparing to a null reference.
However, such an implementation would be considered defective by any
standard and should be fixed rather than worked around!

But in fact, it's a good idea to cast to object before comparing to
null whenever operator== is overriden by the compared type, even if it
doesn't do funny things. The reason is that it's much faster.

When applied to System.Object the "==" and "!=" tokens directly
translate to a single IL instruction each. But when applied to a type
that overrides operator== method calls are generated instead.

I suspect it's for this latter reason that the object cast exists.
System.String does override operator== to achieve "value type
semantics", as they call it; i.e. two strings are equal if they have
the same contents. The object cast saves a method call.


It's interestinig - i was always under impression that overriden operators are in fact virtual, in
other words if you do (Object)StringVariable == null, it would do StringVariable == null, as happens
with virtual functions...

But i guess i had a wrong idea of how operators work...
 
Christoph Nahr said:
Yes -- if the object in question is of a type that overrides
operator== and does funny things when comparing to a null reference.
However, such an implementation would be considered defective by any
standard and should be fixed rather than worked around!

But in fact, it's a good idea to cast to object before comparing to
null whenever operator== is overriden by the compared type, even if it
doesn't do funny things. The reason is that it's much faster.

When applied to System.Object the "==" and "!=" tokens directly
translate to a single IL instruction each. But when applied to a type
that overrides operator== method calls are generated instead.

I suspect it's for this latter reason that the object cast exists.
System.String does override operator== to achieve "value type
semantics", as they call it; i.e. two strings are equal if they have
the same contents. The object cast saves a method call.

Not sure where you get this from, the generated IL is the same in both
cases, there is no cast done.

Willy.
 
MuZZy said:
It's interestinig - i was always under impression that overriden
operators are in fact virtual, in other words if you do
(Object)StringVariable == null, it would do StringVariable == null,
as happens with virtual functions...

But i guess i had a wrong idea of how operators work...

They're not overridden operators - they're overloaded operators.
Polymorphism doesn't come into it.
 
It's interestinig - i was always under impression that overriden operators are in fact virtual

All C# operators are static, so there can't be any polymorphism. The
compiler determines which operator to invoke by looking at the types
of the operands, and then hard-codes the result. You get an error if
the correct operator cannot be determined at compile time, and you'll
get the wrong operator (!) if the type is not visible at compile time.

However, this should not matter because a properly written operator==
always defers the actual comparison to the obligatory Object.Equals
override, and *that* method is indeed polymorphic...
 
Not sure where you get this from, the generated IL is the same in both
cases, there is no cast done.

After some experimentation, it seems you're right regarding String...
apparently the C# compiler special-cases this type.

You get the behavior I describe with other reference types that define
custom equality operators, though.

The quoted code excerpt may have been written with an earlier C#
version in mind that didn't special-case strings. Or else the author
didn't know about this feature, either...
 
Right, String objects are special-cased by the compiler and the CLR .

Willy.
 
Back
Top