Why cast to Object to compare strings?

S

Samuel R. Neff

Why would you cast two strings to objects to compare them? I saw code
in an MS sample on MSDN and don't get it.

if ( (object)name == (object)attr.name ) {

both "name" and "attr.name" are declared as string.

http://msdn.microsoft.com/XML/Build...=/library/en-us/dnxmlnet/html/XmlBkMkRead.asp

Thanks,

Sam


B-Line is now hiring one Washington D.C. area VB.NET
developer for WinForms + WebServices position.
Seaking mid to senior level developer. For
information or to apply e-mail resume to
sam_blinex_com.
 
D

Daniel O'Connell [C# MVP]

Samuel R. Neff said:
Why would you cast two strings to objects to compare them? I saw code
in an MS sample on MSDN and don't get it.

if ( (object)name == (object)attr.name ) {

both "name" and "attr.name" are declared as string.

It is to circumvent operator overloading. By casting to object here, you
force the compiler to use objects == operator, which is a reference
comparison, whereas not casting would have used strings == operator, which
is a string comparison(full character to character compare). I don't know
specifically why the author felt reference comparison was important here(I
can't find it in your example), but that is the effect.

I personally prefer to use object.ReferenceEquals() instead of casting the
two instances to object.
 
S

Samuel R. Neff

Thanks, I didn't realize casting affected operator overload
resolution.

Wish I knew why the writer wanted to use reference comparison for
strings though, it's weird.

Best regards,

Sam


It is to circumvent operator overloading. By casting to object here, you
force the compiler to use objects == operator, which is a reference
comparison, whereas not casting would have used strings == operator, which
is a string comparison(full character to character compare). I don't know
specifically why the author felt reference comparison was important here(I
can't find it in your example), but that is the effect.

I personally prefer to use object.ReferenceEquals() instead of casting the
two instances to object.
B-Line is now hiring one Washington D.C. area VB.NET
developer for WinForms + WebServices position.
Seaking mid to senior level developer. For
information or to apply e-mail resume to
sam_blinex_com.
 
B

Bruce Wood

Are strings compared using character-by-character comparison? Since the
CLR performs string folding, aren't all identical strings really the
same copy anyway? So doesn't == for strings just do a reference
comparison as it does for object?

I don't see the point of comparing strings character-by-character when
you know that all references to identical strings point to the same
memory location...?
 
B

Bruce Wood

This also raises a question about polymorphism and overloading. If I
cast an object up the class hierarchy, will an overloaded method be
called based on the type of the refrence, or based on the type of the
object? For example:

public class A
{
public static DoSomething(A theA) { Console.WriteLine("It's an
A!"); }
public static DoSomething(B theB) { Console.WriteLine("It's a B!");
}
}
public class B : A { ... }

B theB = new B();
A theA = theB;
A.DoSomething(theA);

The question is, which method will be invoked? Will the compiler invoke
DoSomething(A) because the reference it's being passed is an A, or will
it invoke DoSomething(B) because the object to which the reference
points is, in fact, a B?

Or, stated another way, is the call resolved at compile time, or at run
time?
 
B

Bill Butler

Daniel O'Connell said:
It is to circumvent operator overloading. By casting to object here, you
force the compiler to use objects == operator, which is a reference
comparison, whereas not casting would have used strings == operator, which
is a string comparison(full character to character compare). I don't know
specifically why the author felt reference comparison was important here(I
can't find it in your example), but that is the effect.

Uhhhm....I could be mistaken here but....

I thought string.Equals/op_Equality DID use reference comparison
<MEMORY>
Dotnet maintains a collection of strings currently in use
If you create a new string with exactly the same characters as an existing
string
a reference to the original will be returned. (Flyweight pattern)
Thus two strings with the EXACT same characters in the same sequence ARE the
same object.

This allows rapid string comparison (reference compare)
I am pretty sure that this also simplifies using strings in case statements
(within a switch).
<\MEMORY>

This, of course would not apply to case insensitive compares
And CompareTo would still need to test the strings on a per character basis.

I of course could be completely wrong...

Hope this helps
Bill
 
S

Samuel R. Neff

The issue that was confusing me is that override resolution is
different for operators and methods. Operators are static methods and
thus override resolution is done at compile time based on the casted
type. In my testing this is inconsistent with instance method
overrides which are resolved based on actual object type and not the
casted type.

Sam


This also raises a question about polymorphism and overloading. If I
cast an object up the class hierarchy, will an overloaded method be
called based on the type of the refrence, or based on the type of the
object? For example:

public class A
{
public static DoSomething(A theA) { Console.WriteLine("It's an
A!"); }
public static DoSomething(B theB) { Console.WriteLine("It's a B!");
}
}
public class B : A { ... }

B theB = new B();
A theA = theB;
A.DoSomething(theA);

The question is, which method will be invoked? Will the compiler invoke
DoSomething(A) because the reference it's being passed is an A, or will
it invoke DoSomething(B) because the object to which the reference
points is, in fact, a B?

Or, stated another way, is the call resolved at compile time, or at run
time?

B-Line is now hiring one Washington D.C. area VB.NET
developer for WinForms + WebServices position.
Seaking mid to senior level developer. For
information or to apply e-mail resume to
sam_blinex_com.
 
B

Bruce Wood

While coding some data handling classes I just answered my own
question.

Overload resolution works like this:

Which _method signature_ to call is resolved at compile time, based on
the type of the references / value types being passed as arguments.
Therefore, in my example, the compile will tell the run time to look
for a method called DoSomething that takes an argument of type "A",
because that is the type of the reference that was passed.

Polymorphism comes into play when you are invoking a method on an
_instance_. In other words, if you are calling method DoSomethingElse
that is an _instance method_ of A, and overridden in B, then the CLR
decides _at run time_ _which method to call_ based on the actual type
of the object on which the method is invoked. So,

A anA = new B();
A.DoSomethingElse(15);

will call B's "DoSomethingElse", not A's. So, putting it all together:

public class A
{
public virtual void DoSomethingElse(int arg) { ... }
public virtual void DoSomethingELse(double arg) { ... }
}

public class B : A
{
public override void DoSomethingElse(int arg) { ... }
public override void DoSomethingElse(double arg) { ... }
}

if you call

A myA = new B();
myA.DoSomethingElse((double)15);

the method invoked will be B's DoSomethingElse(double). The compiler
decides, at compile time, to invoke a DoSomethingElse that takes a
double parameter, based on the type passed as an argument. The CLR
decides, at run time, to invoke the DoSomethingElse(double) of B
because the object is really a B even though its reference is being
held in a variable of type A.

In the case of static methods, polymorphism doesn't come into play,
because there are no instances. So, everything about the call is
decided at compile time, based on the types of the arguments.

So, yes, saying

if ((object)string1 == (object)string2)

will, in fact, call Object's == operator. However, as I noted in
another post, this should do the same thing as string's == operator, so
I don't see the point.
 
J

Jon Skeet [C# MVP]

Bruce Wood said:
Are strings compared using character-by-character comparison? Since the
CLR performs string folding, aren't all identical strings really the
same copy anyway? So doesn't == for strings just do a reference
comparison as it does for object?

No, because interning is only applied to string literals (and anything
you call Intern on manually).
I don't see the point of comparing strings character-by-character when
you know that all references to identical strings point to the same
memory location...?

They don't. Try the following:

using System;

public class Test
{
static void Main()
{
string x = "x";
string y = x+"y";
string z = x+"y";

Console.WriteLine (y==z);
Console.WriteLine ((object)y==(object)z);
}
}
 
J

Jon Skeet [C# MVP]

Samuel R. Neff said:
The issue that was confusing me is that override resolution is
different for operators and methods. Operators are static methods and
thus override resolution is done at compile time based on the casted
type.

I think you're confusing overriding and overloading. There's no such
thing as operator overriding in C# - but there *is* operator
overloading which, like method overloading, is resolved at compile
time.
In my testing this is inconsistent with instance method
overrides which are resolved based on actual object type and not the
casted type.

It's not inconsistent with overloading though :)
 
J

Jon Skeet [C# MVP]

Bill Butler said:
Uhhhm....I could be mistaken here but....

I thought string.Equals/op_Equality DID use reference comparison

It will do as a first pass, but
<MEMORY>
Dotnet maintains a collection of strings currently in use
If you create a new string with exactly the same characters as an existing
string a reference to the original will be returned. (Flyweight pattern)

Only if the string is a literal.
Thus two strings with the EXACT same characters in the same sequence ARE the
same object.

Nope. That would be incredibly expensive to do *every* time a string
was built.

See my reply to Bruce for an example.
 
B

Bill Butler

Jon Skeet said:
They don't. Try the following:

using System;

public class Test
{
static void Main()
{
string x = "x";
string y = x+"y";
string z = x+"y";

Console.WriteLine (y==z);
Console.WriteLine ((object)y==(object)z);
}
}


Thanks Jon,
I guess I should have tested before posting.
Do you happen to know the actual algorithm for string.Equals()?

I played around a bit and found that it checks for Length equality before
resorting to brute force

Bill
 
J

Jon Skeet [C# MVP]

Bill Butler said:
Thanks Jon,
I guess I should have tested before posting.
Do you happen to know the actual algorithm for string.Equals()?

I played around a bit and found that it checks for Length equality before
resorting to brute force

I don't know, but I can't imagine there'd be much that would be faster
than checking for reference equality, checking for length equality, and
then brute forcing the rest - at least not without making a guess as to
where any difference was most likely to be.
 
B

Bruce Wood

Ah. Yes, that makes perfect sense, because performing interning at run
time on every string construction would be prohibitively expensive.
Silly me. :)
 
S

Samuel R. Neff

Actually as it turns out this is what is hapenning on the sample code
that was the original source of this thread. It's a sample XmlReader
implementation and a few lines above the comparison it has this:

// atomize the name
name = reader.NameTable.Get( name );

So that explains it--the strings are interned so can reference
checking is possible. Object.ReferenceEquals would have been clearer
though (as someone else said earlier).

Thanks for all the feedback,

Sam


Ah. Yes, that makes perfect sense, because performing interning at run
time on every string construction would be prohibitively expensive.
Silly me. :)

B-Line is now hiring one Washington D.C. area VB.NET
developer for WinForms + WebServices position.
Seaking mid to senior level developer. For
information or to apply e-mail resume to
sam_blinex_com.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top