473,385 Members | 1,856 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

struct ToString() not automatically invoked

Everything (er, every class) in C# has ToString() which is
conveniently automatically invoked when using it in Debug.WriteLine()
or in a string concatenation, etc. I made a struct, and I want to
make a method to print out its data in a similar format. So, I did
this:

public struct MyStruct
{
public override string ToString()
{
return ("Hello");
}
}

But, it doesn't get automatically invoked. It complains if I don't
put "public" or "override", so I assume it knows that it's overriding
something (I am not sure what, since it's not a class, and thus not an
object). So:
1. why does it complain without "override"? and
2. why isn't it automatically invoked?

I know classes are references and structs are value types. Since the
struct isn't a class, I don't even know *why* it is complaining about
my creation of a ToString() method in it. I would expect it wouldn't
complain, and also wouldn't be invoked automatically. But, since it
does complain surprisingly, I thought maybe it would also be invoked
automatically, which it doesn't.

Zytan

Mar 7 '07 #1
31 6104
>1. why does it complain without "override"? and

Because a method with the same signature is defined in a base class
(System.Object in this case).

>2. why isn't it automatically invoked?
In what situation is it not invoked? The following prints "Hello
Hello" as expected for me

public struct MyStruct
{
public override string ToString()
{
return ("Hello");
}
}

class Test
{
static void Main()
{
MyStruct m = new MyStruct();
Console.WriteLine("Hello " + m);
}
}
Mattias

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Mar 7 '07 #2
Zytan <zy**********@yahoo.comwrote:
Everything (er, every class) in C# has ToString() which is
conveniently automatically invoked when using it in Debug.WriteLine()
or in a string concatenation, etc. I made a struct, and I want to
make a method to print out its data in a similar format. So, I did
this:

public struct MyStruct
{
public override string ToString()
{
return ("Hello");
}
}

But, it doesn't get automatically invoked.
In what situation? Here's a test which shows it being invoked:

using System;

public struct MyStruct
{
public override string ToString()
{
return ("Hello");
}
}

class Test
{
static void Main()
{
MyStruct foo = new MyStruct();
Console.WriteLine (foo);
}
}
It complains if I don't
put "public" or "override", so I assume it knows that it's overriding
something (I am not sure what, since it's not a class, and thus not an
object).
It still (sort of) derives from object - you are genuinely overriding a
method here. The details are pretty fiddly.
So:
1. why does it complain without "override"? and
Because then you'd be hiding the method instead of overriding it.
2. why isn't it automatically invoked?
When are you expecting it to be automatically invoked?
I know classes are references and structs are value types. Since the
struct isn't a class, I don't even know *why* it is complaining about
my creation of a ToString() method in it. I would expect it wouldn't
complain, and also wouldn't be invoked automatically. But, since it
does complain surprisingly, I thought maybe it would also be invoked
automatically, which it doesn't.
Without more details of when you'd expect it to be invoked, it's
impossible to answer you.

Could you post a short but complete program which demonstrates the
problem?

See http://www.pobox.com/~skeet/csharp/complete.html for details of
what I mean by that.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Mar 7 '07 #3
I don't know what you are doing wrong. It should work.

---------------------------------
using System;

class Test
{
public static void Main()
{
MyStruct x = new MyStruct();
Console.WriteLine("{0}", x);
}
}

public struct MyStruct
{
public override string ToString()
{
return ("Hello");
}
}

-----------------------------------
This definitely prints "Hello"

"Zytan" <zy**********@yahoo.comwrote in message
news:11*********************@j27g2000cwj.googlegro ups.com...
Everything (er, every class) in C# has ToString() which is
conveniently automatically invoked when using it in Debug.WriteLine()
or in a string concatenation, etc. I made a struct, and I want to
make a method to print out its data in a similar format. So, I did
this:

public struct MyStruct
{
public override string ToString()
{
return ("Hello");
}
}

But, it doesn't get automatically invoked. It complains if I don't
put "public" or "override", so I assume it knows that it's overriding
something (I am not sure what, since it's not a class, and thus not an
object). So:
1. why does it complain without "override"? and
2. why isn't it automatically invoked?

I know classes are references and structs are value types. Since the
struct isn't a class, I don't even know *why* it is complaining about
my creation of a ToString() method in it. I would expect it wouldn't
complain, and also wouldn't be invoked automatically. But, since it
does complain surprisingly, I thought maybe it would also be invoked
automatically, which it doesn't.

Zytan

Mar 7 '07 #4
Ok, you guys rock, thanks for posting the code samples. Jon, I've
created a 'complete' program that shows the error (and yes, it
certainly helps to narrow down exactly what is wrong, and most often
shows the err in your ways). The problem occurs when I have my *own
function* that accepts a string. In this case, the conversion from
struct to string does not implicitly take place.

class Program
{
public struct MyStruct
{
public int x;
public override string ToString()
{
return "Hello!";
}
}
static void Main(string[] args)
{
MyStruct s;
s.x = 5;
Print(s); // doesn't compile
Print(s.ToString()); // compiles
}
static void Print(string s)
{
Console.WriteLine(s);
}
}

Zytan

Mar 7 '07 #5
1. why does it complain without "override"? and
>
Because a method with the same signature is defined in a base class
(System.Object in this case).
Ok, so, structs DO derive from object. Strange. I guess the evidence
suggest that, doesn't it?
2. why isn't it automatically invoked?

In what situation is it not invoked?
Please see my program in another post in this thread.

Thanks, Mattias

Zytan

Mar 7 '07 #6
But, it doesn't get automatically invoked.
>
In what situation?
Please see my program in another post.
It complains if I don't
put "public" or "override", so I assume it knows that it's overriding
something (I am not sure what, since it's not a class, and thus not an
object).

It still (sort of) derives from object - you are genuinely overriding a
method here. The details are pretty fiddly.
Ah.
So:
1. why does it complain without "override"? and

Because then you'd be hiding the method instead of overriding it.
Yes, of course. Now that I know it's derived from object, it makes
sense.
2. why isn't it automatically invoked?

When are you expecting it to be automatically invoked?
It's when I pass it to my own function that accepts a string
parameter.
Please see the program in another post.

Thanks, Jon

Zytan

Mar 7 '07 #7
I don't know what you are doing wrong. It should work.

I don't think I am doing anything wrong. Call your own function that
takes a string instead of Console.WriteLine in your program, and
you'll see that it doesn't work.

Please see my program in another post.

Thanks, Bill.

Zytan

Mar 7 '07 #8
Zytan <zy**********@yahoo.comwrote:
Ok, you guys rock, thanks for posting the code samples. Jon, I've
created a 'complete' program that shows the error (and yes, it
certainly helps to narrow down exactly what is wrong, and most often
shows the err in your ways). The problem occurs when I have my *own
function* that accepts a string. In this case, the conversion from
struct to string does not implicitly take place.
No, it doesn't - and it doesn't for classes either, thankfully. Why did
you expect that it would?

You could add your own implicit conversion to a string, although I
wouldn't recommend it.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Mar 7 '07 #9
"Zytan" <zy**********@yahoo.comwrote in message
news:11**********************@64g2000cwx.googlegro ups.com...
>I don't know what you are doing wrong. It should work.

I don't think I am doing anything wrong. Call your own function that
takes a string instead of Console.WriteLine in your program, and
you'll see that it doesn't work.
You could overload your Print method a few times to get the behavior
that you desire

for instance, this would work.

static void Print(object obj)
{
Console.WriteLine(obj);
}
You could make your Print method accept formatting strings as well if
you write those overloads

Good luck
Bill

Mar 7 '07 #10
No, it doesn't - and it doesn't for classes either, thankfully.

Why thankfully?
Why did you expect that it would?
It does for Console.WriteLine which takes a string.
Why not for MyOwnFunction which takes a string?
I see no difference between the two.

(I personally was surprised that C# does this at all implicitly, since
it does so much to ensure proper / strict type checking, so I don't
care that I must do astruct.ToString() manually.)
You could add your own implicit conversion to a string, although I
wouldn't recommend it.
Ok, I don't think you mean using Print(astruct.ToString()), so you
must mean adding such capability to the struct itself, such that I can
do Print(astruct). I'd prefer not to do that anyway. But, why is it
needed? And why is it not recommended?

Zytan

Mar 7 '07 #11
I don't think I am doing anything wrong. Call your own function that
takes a string instead of Console.WriteLine in your program, and
you'll see that it doesn't work.

You could overload your Print method a few times to get the behavior
that you desire

for instance, this would work.

static void Print(object obj)
{
Console.WriteLine(obj);
}
Yes, you're right, that works!

But, why does this work, and using 'string' as the parameter type
doesn't? Doesn't Console.WriteLine also accept 'string', this being
no different than my original Print method that takes a string? What
gives?
You could make your Print method accept formatting strings as well if
you write those overloads
Please elaborate, Bill, if you don't mind. I am unsure what you mean
by accepting 'formatting strings'? You mean like: Print(string
format, params object[] args), in the way Console.WriteLine does?
Good luck
Thanks!

Zytan

Mar 7 '07 #12
Console.WriteLine can take a string, and it is also overloaded numerous ways
to take Boolean, Decimal, int, etc. One of the overloads takes an Object.

You have *assumed* that when you do Console.WriteLine( yourobject ) that you
have in fact invoked the version that takes the String argument.

I severely doubt this is the case. I think you are invoking the version that
takes an object, and *that* version of Console.WriteLine does the
ToString( ) for you.

So you are presuming there is an implicit *conversion* going on here when in
fact I don't think there is.

If you want your function to take your object without requiring a
ToString( ) conversion, do exactly what Console.WriteLine does and have it
accept an Object and then have the function perform the ToString( ). Note
that a ToString( ) still occurs, it's just that you don't have to hand-code
it everywhere.

But be warned that implicit conversions (or mechanisms that look like they
behave like implicit conversions) can make code more mysterious. When used
in appropriates cases (and Console.WriteLine is an appropriate case because
it is arguably generic behaviour), it makes for an effective interface.

When used for the sake of reducing your typing, then you have chosen this
requirement over and above good design.

Kevin

"Zytan" <zy**********@yahoo.comwrote in message
news:11**********************@c51g2000cwc.googlegr oups.com...
>No, it doesn't - and it doesn't for classes either, thankfully.

Why thankfully?
>Why did you expect that it would?

It does for Console.WriteLine which takes a string.
Why not for MyOwnFunction which takes a string?
I see no difference between the two.

(I personally was surprised that C# does this at all implicitly, since
it does so much to ensure proper / strict type checking, so I don't
care that I must do astruct.ToString() manually.)
>You could add your own implicit conversion to a string, although I
wouldn't recommend it.

Ok, I don't think you mean using Print(astruct.ToString()), so you
must mean adding such capability to the struct itself, such that I can
do Print(astruct). I'd prefer not to do that anyway. But, why is it
needed? And why is it not recommended?

Zytan

Mar 7 '07 #13
<snip
>for instance, this would work.

static void Print(object obj)
{
Console.WriteLine(obj);
}

Yes, you're right, that works!

But, why does this work, and using 'string' as the parameter type
doesn't? Doesn't Console.WriteLine also accept 'string', this being
no different than my original Print method that takes a string? What
gives?
No, it is using object as the parameter type in this case.
Console.WriteLine calls ToString() on any object passed to it.
Console.WriteLine has about 20 overloads {So do the other classes that
expose WriteLine}
see:
http://msdn2.microsoft.com/en-us/lib...writeline.aspx

Samples:
Console.WriteLine("Hello"); // WriteLine(string);
Console.WriteLine(333); // WriteLine(int);
X x = new X();
Console.WriteLine(x); // WriteLine(object);
Console.WriteLine("[{0}]",33"); // WriteLine(string, object);
Console.WriteLine("{0}^2={1}", 5, 5*5); // WriteLine(string, object,
object);
etc

>
>You could make your Print method accept formatting strings as well if
you write those overloads

Please elaborate, Bill, if you don't mind. I am unsure what you mean
by accepting 'formatting strings'? You mean like: Print(string
format, params object[] args), in the way Console.WriteLine does?
Yes, You simply provide your own overloads to mimic those used in
Console.WriteLine
For instance, Suppose you wanted to slap a timestamp on everything that
you send to YOUR Print method.
You create a few overloads for Print and voila

Here..take a look.
using System;

class Program
{
public struct MyStruct
{
public int x;
public override string ToString()
{
return "Hello!";
}
}
static void Main(string[] args)
{

MyStruct s;
s.x = 5;
Print("qwerty");
Print(s);
Print("[{0}]",33);
Print("{0}^2={1}", 5, 5*5);
}

static void Print(object obj)
{
Print(obj.ToString());
}

public static void Print(string format, object obj1)
{
string data =string.Format(format, obj1);
Print(data);
}

public static void Print(string format, object obj1, object obj2)
{
string data =string.Format(format, obj1, obj2);
Print(data);
}

public static void Print(string format, object obj1, object obj2,
object obj3)
{
string data =string.Format(format, obj1, obj2, obj3);
Print(data);
}

public static void Print(string format, params object[] objs)
{
string data =string.Format(format, objs);
Print(data);
}

public static void Print(string data)
{
Console.WriteLine("{0:HH:mm:ss.ff} {1}", DateTime.Now, data );
}

}

Mar 8 '07 #14
But, why does this work, and using 'string' as the parameter type
doesn't? Doesn't Console.WriteLine also accept 'string', this being
no different than my original Print method that takes a string? What
gives?

No, it is using object as the parameter type in this case.
Console.WriteLine calls ToString() on any object passed to it.
Console.WriteLine has about 20 overloads {So do the other classes that
expose WriteLine}
see:http://msdn2.microsoft.com/en-us/lib...writeline.aspx
Yes, I knew it had (single parameter) overloads (although I was never
sure why, since ToString() is invoked on anything passed in). But,
the one I was calling was Console.WriteLine(string), not
WriteLine(object). But yes, MSDN shows:
http://msdn2.microsoft.com/en-us/library/swx4tc5e.aspx
"If value is a null reference (Nothing in Visual Basic), only the line
terminator is written. Otherwise, the ToString method of value is
called to produce its string representation, and the resulting string
is written to the standard output stream."

So, now it makes sense. Since ToString() is available for everything
(including structs, as I've found), WriteLine(object) works for
anything. Add, the compiler doesn't just blindly convert anything
into a string as it wishes, it was merely calling WriteLine(object).

(Although, when you concatenate strings, it does invoke ToString()
automatically, so it seems to be implicitly converting anything into a
string as it wishes, so that's strange.)

(And, this begs the question: Why are the other [single parameter]
WriteLine overloads even needed, if you have WriteLine(object)?)
Yes, You simply provide your own overloads to mimic those used in
Console.WriteLine
For instance, Suppose you wanted to slap a timestamp on everything that
you send to YOUR Print method.
You create a few overloads for Print and voila
Right, I could mimic Console.WriteLine. Well, my function is for
logging, so perhaps I should just use the Print(object) style, and let
it call the ToString() on anything I pass in. Isn't that good enough
to cover basic Console.WriteLine (the single parameter overloads)
functionality?

Zytan

Mar 8 '07 #15
You have *assumed* that when you do Console.WriteLine( yourobject ) that you
have in fact invoked the version that takes the String argument.
Indeed I have.
I severely doubt this is the case. I think you are invoking the version that
takes an object, and *that* version of Console.WriteLine does the
ToString( ) for you.
Yup. That's exactly what's happening.
So you are presuming there is an implicit *conversion* going on here when in
fact I don't think there is.
Yes! And I think this arose from the fact that concantenating strings
implicitly invokes ToString(), and I may even have read somewhere (or
maybe just thought it myself) that the same thing happens when using
Debug.WriteLine or Console.WriteLine.
If you want your function to take your object without requiring a
ToString( ) conversion, do exactly what Console.WriteLine does and have it
accept an Object and then have the function perform the ToString( ). Note
that a ToString( ) still occurs, it's just that you don't have to hand-code
it everywhere.
Yup! This is the solution. Thanks.
But be warned that implicit conversions (or mechanisms that look like they
behave like implicit conversions) can make code more mysterious. When used
in appropriates cases (and Console.WriteLine is an appropriate case because
it is arguably generic behaviour), it makes for an effective interface.
I totally agree. My function is a logfile WriteLine-style of
function, so this should be one of those cases. I wouldn't do this
elsewhere, and I actually disliked the thought that C#, with all of
its strict type checking and explicit type conversion requirements
(like bool and int), was actually doing something as horrid as
implicitly converting anything I give it to a string! Now I feel
better. And I wouldn't implement this normally, except, as you say,
for WriteLine-style behaviour, it's accepted, and ok.
When used for the sake of reducing your typing, then you have chosen this
requirement over and above good design.
Yes. I prefer to be verbose and proper, than quick and dirty.

Thanks, Kevin

Zytan
Mar 8 '07 #16
"Zytan" <zy**********@yahoo.comwrote in message
news:11**********************@8g2000cwh.googlegrou ps.com...
<snip>
(And, this begs the question: Why are the other [single parameter]
WriteLine overloads even needed, if you have WriteLine(object)?)
Efficiency. That is the same reason it has
Writeline(string format, obj1);
Writeline(string format, obj1, obj2);
Writeline(string format, obj1, obj2, obj3);

when
Writeline(string format, params object[] objs);
would have sufficed. These overrides perform better.
>Yes, You simply provide your own overloads to mimic those used in
Console.WriteLine
For instance, Suppose you wanted to slap a timestamp on everything
that
you send to YOUR Print method.
You create a few overloads for Print and voila

Right, I could mimic Console.WriteLine. Well, my function is for
logging, so perhaps I should just use the Print(object) style, and let
it call the ToString() on anything I pass in. Isn't that good enough
to cover basic Console.WriteLine (the single parameter overloads)
functionality?
It would work. You have to decide if it is "Good enough".

Good Luck
Bill
Mar 8 '07 #17
Zytan <zy**********@yahoo.comwrote:
No, it doesn't - and it doesn't for classes either, thankfully.

Why thankfully?
Because implicit conversions are generally a bad idea.
Why did you expect that it would?

It does for Console.WriteLine which takes a string.
Why not for MyOwnFunction which takes a string?
I see no difference between the two.
Console.WriteLine is overloaded, and there's one overload which takes
an object.
(I personally was surprised that C# does this at all implicitly, since
it does so much to ensure proper / strict type checking, so I don't
care that I must do astruct.ToString() manually.)
Exactly - strictness is generally a good idea.
You could add your own implicit conversion to a string, although I
wouldn't recommend it.

Ok, I don't think you mean using Print(astruct.ToString()), so you
must mean adding such capability to the struct itself, such that I can
do Print(astruct). I'd prefer not to do that anyway. But, why is it
needed? And why is it not recommended?
I don't recommend it because I don't like conversions going on which
aren't obvious when reading the code. I think I've covered why it's
"needed" already.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Mar 8 '07 #18
Bill Butler <qw****@asdf.comwrote:
"Zytan" <zy**********@yahoo.comwrote in message
news:11**********************@8g2000cwh.googlegrou ps.com...
<snip>
(And, this begs the question: Why are the other [single parameter]
WriteLine overloads even needed, if you have WriteLine(object)?)

Efficiency. That is the same reason it has
Writeline(string format, obj1);
Writeline(string format, obj1, obj2);
Writeline(string format, obj1, obj2, obj3);

when
Writeline(string format, params object[] objs);
would have sufficed. These overrides perform better.
No, that's not for efficiency - it's to help those languages which
don't support "params" parameters automatically. Internally the
overloads which don't take an array create an array anyway.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Mar 8 '07 #19
Zytan <zy**********@yahoo.comwrote

<snip>
(Although, when you concatenate strings, it does invoke ToString()
automatically, so it seems to be implicitly converting anything into a
string as it wishes, so that's strange.)
String concatenation is an exception (which is part of the C# language,
by the way, not something done automatically by .NET) which is just for
sake of convenience. Sometimes purity comes second to practicality :)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Mar 8 '07 #20
"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:MP************************@msnews.microsoft.c om...
Bill Butler <qw****@asdf.comwrote:
>"Zytan" <zy**********@yahoo.comwrote in message
news:11**********************@8g2000cwh.googlegro ups.com...
<snip>
(And, this begs the question: Why are the other [single parameter]
WriteLine overloads even needed, if you have WriteLine(object)?)

Efficiency. That is the same reason it has
Writeline(string format, obj1);
Writeline(string format, obj1, obj2);
Writeline(string format, obj1, obj2, obj3);

when
Writeline(string format, params object[] objs);
would have sufficed. These overrides perform better.

No, that's not for efficiency - it's to help those languages which
don't support "params" parameters automatically. Internally the
overloads which don't take an array create an array anyway.
Thanks for the info.

Bill
Mar 9 '07 #21
(And, this begs the question: Why are the other [single parameter]
WriteLine overloads even needed, if you have WriteLine(object)?)

Efficiency. That is the same reason it has
Writeline(string format, obj1);
Writeline(string format, obj1, obj2);
Writeline(string format, obj1, obj2, obj3);

when
Writeline(string format, params object[] objs);
would have sufficed. These overrides perform better.
Right.
Right, I could mimic Console.WriteLine. Well, my function is for
logging, so perhaps I should just use the Print(object) style, and let
it call the ToString() on anything I pass in. Isn't that good enough
to cover basic Console.WriteLine (the single parameter overloads)
functionality?

It would work. You have to decide if it is "Good enough".
Yes, it is. Thanks, Bill

Zytan

Mar 12 '07 #22
(Although, when you concatenate strings, it does invoke ToString()
automatically, so it seems to be implicitly converting anything into a
string as it wishes, so that's strange.)

String concatenation is an exception (which is part of the C# language,
by the way, not something done automatically by .NET) which is just for
sake of convenience. Sometimes purity comes second to practicality :)
Ah, ok. Yes, and I think everyone's happy with this.

Zytan

Mar 12 '07 #23
Zytan wrote:
>So you are presuming there is an implicit *conversion* going on here when in
fact I don't think there is.

Yes! And I think this arose from the fact that concantenating strings
implicitly invokes ToString(), and I may even have read somewhere (or
maybe just thought it myself) that the same thing happens when using
Debug.WriteLine or Console.WriteLine.
The same thing actually happens, and it's not an implicit conversion in
either case.

If you concatenate two strings, the string.Concat(string, string) method
is used. But if you are concatenating a string with something else, the
string.Concat(object, object) method is used. The ToString method is
called, but not before the values is sent to the Concat method, but
inside the Concat method.

There is something that is done implicitly if you are using a value type
in this way, though, and that is boxing. As the method takes the type
object, a new object has to be created that contains the value from the
value type.

So the expression "foo" + bar where bar is a value type is equivalent to
"foo" + new object(bar). (Not that the object constructor takes
parameters, but you get the idea.)

--
Göran Andersson
_____
http://www.guffa.com
Mar 12 '07 #24
On Mar 7, 3:06 pm, "Zytan" <zytanlith...@yahoo.comwrote:
No, it doesn't - and it doesn't for classes either, thankfully.

Why thankfully?
Why did you expect that it would?

It does for Console.WriteLine which takes a string.
Why not for MyOwnFunction which takes a string?
I see no difference between the two.

(I personally was surprised that C# does this at all implicitly, since
it does so much to ensure proper / strict type checking, so I don't
care that I must do astruct.ToString() manually.)
You could add your own implicit conversion to a string, although I
wouldn't recommend it.

Ok, I don't think you mean using Print(astruct.ToString()), so you
must mean adding such capability to the struct itself, such that I can
do Print(astruct). I'd prefer not to do that anyway. But, why is it
needed? And why is it not recommended?
Just to clear up the final mystery in this thread, an "implicit
conversion" is a static method that you can write as part of your
class or struct that tells the compiler that your type can silently be
converted to some other type.

An example may help. I have written a Fraction struct. It allows me to
represent rational numbers (the company I work for is in the wood
business, so we often have to deal with values like "15 7 / 32" or
"1 / 2"). I have an implicit conversion from Fraction to decimal. This
means that I can do this:

Fraction half = new Fraction(1, 2);
decimal d = half;

On that second line, the compiler invokes my implicit conversion
function to convert the Fraction to a decimal.

You can also write explicit conversions: conversions that require the
programmer to specify an explicit cast. If I had written the Fraction-
to-decimal conversion as explicit, I would be forced to do this:

Fraction half = new Fraction(1, 2);
decimal d = (decimal)half;

You can read more here:

http://msdn2.microsoft.com/en-us/lib...0a(VS.80).aspx

Conversions (explicit and implicit) and operator overloading are best
used sparingly, as they can be horribly abused (as they can be in C++,
too). I tend to restrict mine to structs (value types) and then only
in situations in which (I believe) it will be abundantly clear to the
reader of the code what is going on.

As a counterexample, this:

WarehouseDetail warehouseInfo =
stockItem.GetWarehouseDetail(warehouse);

is much easier to understand than this:

WarehouseDetail warehouseInfo = stockItem + warehouse;

although the latter is simple to achieve with an operator overload.

Mar 12 '07 #25
Jon Skeet [C# MVP] wrote:
Zytan <zy**********@yahoo.comwrote

<snip>
>(Although, when you concatenate strings, it does invoke ToString()
automatically, so it seems to be implicitly converting anything into a
string as it wishes, so that's strange.)

String concatenation is an exception (which is part of the C# language,
by the way, not something done automatically by .NET) which is just for
sake of convenience. Sometimes purity comes second to practicality :)
Actually it's not an exception at all. The same thing happens as with
the WriteLine method; there is an overload that take object parameters.

When you concatenate two strings, the string.Concat(string, string)
method is used, but when you are concatenating a string with something
else, the string.Concat(object, object) method is used. The ToString
method is used, but not implicitly before the value is used, but inside
the Concat method.

--
Göran Andersson
_____
http://www.guffa.com
Mar 12 '07 #26
Göran Andersson <gu***@guffa.comwrote:
(Although, when you concatenate strings, it does invoke ToString()
automatically, so it seems to be implicitly converting anything into a
string as it wishes, so that's strange.)
String concatenation is an exception (which is part of the C# language,
by the way, not something done automatically by .NET) which is just for
sake of convenience. Sometimes purity comes second to practicality :)
Actually it's not an exception at all. The same thing happens as with
the WriteLine method; there is an overload that take object parameters.
Well, I'd still say that it *is* an exception. At the *language* level
it appears to be an overloaded operator, but it actually isn't.

The underlying calls are irrelevant to the fact that it's a
specifically defined operator in C#, whereas WriteLine certainly isn't!

The string.Concat method isn't the exception here, it's the fact that
it's called when you do "foo" + x that is the exception.

I think I see what you're getting at though - it's not the C# compiler
that's calling ToString(), it's string.Concat. I certainly agree on
that point. But the context of my post was that Zytan expected ToString
to be called to allow any object to be passed to a method with a string
parameter, because he'd seen the string concatenation operator.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Mar 12 '07 #27
Jon Skeet [C# MVP] wrote:
Göran Andersson <gu***@guffa.comwrote:
>>>(Although, when you concatenate strings, it does invoke ToString()
automatically, so it seems to be implicitly converting anything into a
string as it wishes, so that's strange.)
String concatenation is an exception (which is part of the C# language,
by the way, not something done automatically by .NET) which is just for
sake of convenience. Sometimes purity comes second to practicality :)
Actually it's not an exception at all. The same thing happens as with
the WriteLine method; there is an overload that take object parameters.

Well, I'd still say that it *is* an exception. At the *language* level
it appears to be an overloaded operator, but it actually isn't.

The underlying calls are irrelevant to the fact that it's a
specifically defined operator in C#, whereas WriteLine certainly isn't!

The string.Concat method isn't the exception here, it's the fact that
it's called when you do "foo" + x that is the exception.
Yes, the fact that the compiler implements the concatenation operator
with the Concat method is an exception. But once you are past that it
all follows the pattern. There is no magic conversions added by the
compiler.
I think I see what you're getting at though - it's not the C# compiler
that's calling ToString(), it's string.Concat. I certainly agree on
that point. But the context of my post was that Zytan expected ToString
to be called to allow any object to be passed to a method with a string
parameter, because he'd seen the string concatenation operator.
Yes, and my point was that if you realise what the concatenation
operator really does, you see that there is no conversions added to the
code.

When you see that the compiler doesn't add any ToString calls in that
case, you won't expect it to do that anywhere else.

--
Göran Andersson
_____
http://www.guffa.com
Mar 12 '07 #28
When you concatenate two strings, the string.Concat(string, string)
method is used, but when you are concatenating a string with something
else, the string.Concat(object, object) method is used. The ToString
method is used, but not implicitly before the value is used, but inside
the Concat method.
Thanks for the details, Göran, it's easier to follow what's happening
when you know them.

Zytan

Mar 13 '07 #29
I think I see what you're getting at though - it's not the C# compiler
that's calling ToString(), it's string.Concat. I certainly agree on
that point. But the context of my post was that Zytan expected ToString
to be called to allow any object to be passed to a method with a string
parameter, because he'd seen the string concatenation operator.
Yes, I did.
Yes, and my point was that if you realise what the concatenation
operator really does, you see that there is no conversions added to the
code.

When you see that the compiler doesn't add any ToString calls in that
case, you won't expect it to do that anywhere else.
Right. Thanks for the help, guys.

Zytan

Mar 13 '07 #30
If you concatenate two strings, the string.Concat(string, string) method
is used. But if you are concatenating a string with something else, the
string.Concat(object, object) method is used. The ToString method is
called, but not before the values is sent to the Concat method, but
inside the Concat method.
I ran into this myself when I did:
Console.WriteLine("x = " + n + 1 + " elements.");
and of course it didn't work as I expected. I needed to put () around
n+1 to make it work.
There is something that is done implicitly if you are using a value type
in this way, though, and that is boxing. As the method takes the type
object, a new object has to be created that contains the value from the
value type.
Ah, I haven't looked into boxing, yes, but I've seen it in top 10 list
of things to know about when learning C#.
So the expression "foo" + bar where bar is a value type is equivalent to
"foo" + new object(bar). (Not that the object constructor takes
parameters, but you get the idea.)
Right.

thanks again,

Zytan

Mar 13 '07 #31
Just to clear up the final mystery in this thread, an "implicit
conversion" is a static method that you can write as part of your
class or struct that tells the compiler that your type can silently be
converted to some other type.

An example may help. I have written a Fraction struct. It allows me to
represent rational numbers (the company I work for is in the wood
business, so we often have to deal with values like "15 7 / 32" or
"1 / 2"). I have an implicit conversion from Fraction to decimal. This
means that I can do this:

Fraction half = new Fraction(1, 2);
decimal d = half;

On that second line, the compiler invokes my implicit conversion
function to convert the Fraction to a decimal.

You can also write explicit conversions: conversions that require the
programmer to specify an explicit cast. If I had written the Fraction-
to-decimal conversion as explicit, I would be forced to do this:

Fraction half = new Fraction(1, 2);
decimal d = (decimal)half;

You can read more here:

http://msdn2.microsoft.com/en-us/lib...0a(VS.80).aspx
Ok, thanks, Bruce. Your example is clear.
Conversions (explicit and implicit) and operator overloading are best
used sparingly, as they can be horribly abused (as they can be in C++,
too). I tend to restrict mine to structs (value types) and then only
in situations in which (I believe) it will be abundantly clear to the
reader of the code what is going on.
Yes, as do I. I prefer readability even if it's verbose.

Zytan

Mar 13 '07 #32

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

18
by: Steven Bethard | last post by:
In the "empty classes as c structs?" thread, we've been talking in some detail about my proposed "generic objects" PEP. Based on a number of suggestions, I'm thinking more and more that instead of...
20
by: fix | last post by:
Hi all, I feel unclear about what my code is doing, although it works but I am not sure if there is any possible bug, please help me to verify it. This is a trie node (just similar to tree nodes)...
21
by: hermes_917 | last post by:
I want to use memcpy to copy the contents of one struct to another which is a superset of the original struct (the second struct has extra members at the end). I wrote a small program to test...
6
by: SB | last post by:
I feel dumb to ask because I bet this is a simple question... Looking at the code below, can someone please explain why I get two different values in my Marshal.SizeOf calls (see the commented...
0
by: Alvaro Enriquez de Luna | last post by:
Hello everybody. I am trying to use in C# a dll developed in C. I am founding problems with C structs. While my C struct does not include anything related with char or char *, everyting works ok,...
6
by: Eric | last post by:
This IS material from a CS class on object oriented programming. It is NOT my homework. Consider the following: struct A {short i; void f () {cout << "A::f()\n";}}; struct B : A {long ...
74
by: Zytan | last post by:
I have a struct constructor to initialize all of my private (or public readonly) fields. There still exists the default constructor that sets them all to zero. Is there a way to remove the...
4
by: call_me_anything | last post by:
I have different kind of data structures in different applications. The data structures are big and complex and I would like to print the members of each struct. Can we write a generic piece of...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.