Is this really correct compiler behaviour

G

Guest

I found a really strange quirk in the C# compiler, which I can't beleive is
proper behaviour. If I define a class thus:
public class MyClass
{
public override string ToString()
{
return base.ToString();
}
}

and then call it thus:

MyClass myClass = new MyClass();
string test1 = myClass;

it does not compile, because it cannot implicitly convert myClass to a string.
But if I call it thus:

MyClass myClass = new MyClass();
string test1 = myClass + "";

it compiles fine. I'd be interested to know if anyone thinks that makes sense.
 
J

John Duval

I found a really strange quirk in the C# compiler, which I can't beleive is
proper behaviour. If I define a class thus:
public class MyClass
{
public override string ToString()
{
return base.ToString();
}
}

and then call it thus:

MyClass myClass = new MyClass();
string test1 = myClass;

it does not compile, because it cannot implicitly convert myClass to a string.
But if I call it thus:

MyClass myClass = new MyClass();
string test1 = myClass + "";

it compiles fine. I'd be interested to know if anyone thinks that makes sense.

Hi Dave,
Yes I think it makes sense. I think you might have wanted to say
"string test1 = myClass.ToString();" instead of "string test1 =
myClass;". The compiler won't do the implicit conversion for you.
Even if you've overridden ToString() it won't do this conversion --
all objects have a default ToString() implementation so the fact that
you've overridden the function doesn't really change anything,

In the case where you append an empty string, the + operator causes
the compiler to check to see if myClass can be converted to a string.

John
 
B

Barry Kelly

Dave said:
I found a really strange quirk in the C# compiler, which I can't beleive is
proper behaviour.

It's by design.
MyClass myClass = new MyClass();
string test1 = myClass;

it does not compile, because it cannot implicitly convert myClass to a string.
But if I call it thus:

MyClass myClass = new MyClass();
string test1 = myClass + "";

it compiles fine. I'd be interested to know if anyone thinks that makes sense.

Imagine that there's two versions of the '+' operator defined on
System.String, thusly:

public static string operator +(string left, object right);
public static string operator +(object left, string right);

(There isn't, because much string stuff is built-in.)

What you're expecting amounts to something more like this, defined on
System.Object:

public static implicit operator string(object value);

I think it's a compromise between the usefulness of having string
representations of objects, versus the downside of having objects turn
into strings at the drop of a hat. Implicit conversions that lose
information are usually considered to be a bad idea; at least the '+'
operator requires that you have an expression of string type on the left
or right beforehand.

-- Barry
 
G

Guest

Of course the correct thing to do is to use ToString() explicitly, my example
is to illustrate the odd behaviour which does seem to be extremely
inconsistant. I mean either myClass can be implicitly converted to a string
or it can't, it shouldn't depend on the context like this surely (it
certainly wouldn't in C++).
 
R

rossum

I found a really strange quirk in the C# compiler, which I can't beleive is
proper behaviour. If I define a class thus:
public class MyClass
{
public override string ToString()
{
return base.ToString();
}
}

and then call it thus:

MyClass myClass = new MyClass();
string test1 = myClass;

it does not compile, because it cannot implicitly convert myClass to a string.
But if I call it thus:

MyClass myClass = new MyClass();
string test1 = myClass + "";

it compiles fine. I'd be interested to know if anyone thinks that makes sense.

If one of its operands is a string then the concatenation '+' operator
will look for either an implicit type conversion or ToString() if the
other operand is not a string.

The assignment operator '=' only looks for built in or 'implicit' type
conversions, it does not look for ToString().

If you want your assignment to work as written then define an implicit
type conversion:

implicit operator string(MyClass mc) { return mc.ToString(); }

The assignment operator will recognise this implicit type conversion.

rossum
 
G

Guest

Actually I don't want the assignment to work as written, quite the opposite.
This arose because of some code of mine that compiled without error - it was
only when I removed the concatenated string that it suddenly produced
compiler errors and I realised that I had unknowingly used completely the
wrong variable. I would actually expect both of the statements in my example
to fail to compile.
 
J

Jon Skeet [C# MVP]

Dave said:
I found a really strange quirk in the C# compiler, which I can't beleive is
proper behaviour. If I define a class thus:
public class MyClass
{
public override string ToString()
{
return base.ToString();
}
}

and then call it thus:

MyClass myClass = new MyClass();
string test1 = myClass;

it does not compile, because it cannot implicitly convert myClass to a string.
But if I call it thus:

MyClass myClass = new MyClass();
string test1 = myClass + "";

it compiles fine. I'd be interested to know if anyone thinks that makes sense.

From http://www.jaggersoft.com/csharp_standard/14.7.4.htm

<quote>
The binary + operator performs string concatenation when one or both
operands are of type string. If an operand of string concatenation is
null, an empty string is substituted. Otherwise, any non-string
argument is converted to its string representation by invoking the
virtual ToString method inherited from type object. If ToString returns
null, an empty string is substituted.
</quote>
 

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