Exception's ToString() method - c#

I found in someones code following :
catch (Exception exception)
{
Console.WriteLine(exception.ToString());
}
Resharper is graying out the ToString() call which is as always a great suggestion.
How does this C# code work without it ? Will ToString() be called implicitly ?

Console.WriteLine has an overload that takes an object. This object's ToString method is called internally so there's no need for you to add ToString in the first place.

If the exception is being used within a string... For example "something" + exception.ToString() or String.Format("... {0}", exception), then yes, ToString will be called without you having to call it explicitly.
And... as you updated your example, calling Console.WriteLine() against any object value, ToString will be called. Here's the documentation, with as much detail as you could possibly want.

I assume the something is string concatenation or used as a parameter in a formatted string, then yes, ToString is called implicitly.
UPDATE FOLLOWING QUESTION UPDATE
Console has an overload of WriteLine that accepts an object argument, in this version on the method ToString is called if the passed instance is not null - R# is aware of this and suggests the choice of the preferable overload.

Related

Explicit vs implicit call of ToString()

Is there any benefit in calling the ToString() method on a string builder when the method call accepts the type object as it's parameter?
StringBuilder sb = new StringBuilder("Hello");
System.Console.WriteLine(sb);
OR
System.Console.WriteLine(sb.ToString());
From what I know the WriteLine takes an object as an overload, my guess is the ToString() method is then called on the object, which then calls the StringBuilder.ToString() method and returns the expected string value.
So again, is there any benefit in explictly calling ToString()? Could you please justify your answer?
"my guess is the ToString() method is then called on the object"
If you look at MSDN you see that there is no overload that consumes a StringBuilder directly, so the one which accepts anything(object) is used.
So your guess was correct, it will just call ToString.
If value is null, 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.
Then i would prefer to call it myself since it's more readable and you gain nothing by passing the StringBuilder.
The only benefit is that it is clear what you're doing. If you can state something explicitly do it - it makes the code more readable.
Is there any benefit in explicitly calling ToString()?
Console.WriteLine(object) will first check if the object is null and if so simply output an empty line. Calling ToString on a null object will result in a NullReferenceException.
So WriteLine(object) has built in null-safety, and the result for null will be the same as a non-null object that outputs an empty string. Depending on the context, that null safety could be convenient, or it could cause undesired behavior.
In short, it's more beneficial to call ToString() if you don't want a NullReferenceException to be suppressed.
No, there's no benefit. Tools with good static analysis capabilities like ReSharper will actually let you know that the call is redundant and can be safely removed.

Should we always specify ToString() explicitly?

I have a custom class structure as follows.
public interface Stuff { }
public Thing : Stuff
{
public new String ToString() { return "That's the thing!"; }
}
Then, in other parts of my code I have a method that takes a String object as a parameter. The first line compiles, while the second one doesn't. I thought that ToString was called by default when sending in an object. And Stuff, being inherited from Object class should have ToString already implemented (and also, in my case, shadowed by my implementation).
Thing thing = new Thing();
MustHaveString(thing.ToString());
MustHaveString(thing);
What do I miss?
You're probably getting confused because of calls such as String.Format and Console.WriteLine, as well as string concatenation operator, which call ToString implcitly.
This isn't a general rule though. In general, if you need a string, you need to either call ToString explicitly or have some other conversion. I wouldn't recommend creating implicit conversions to string - they're likely to cause more pain than joy.
I'd also recommend against creating a new ToString method. Instead, you should override the one declared by object. Hiding methods is almost always a bad idea; there are a few cases where you really want to do it (e.g. to change the return type) but it should be avoided where possible.
Assuming MustHaveString looks something like:
public void MustHaveString(string arg)
Then simply saying thing results in a compile error, unless thing has an implicit conversion to string. Without the implicit conversion, you must do thing.ToString(). If, however, your code is like:
string myString = "This is a thing: " + thing;
Then the ToString is implicitly called, so it's optional.
In most cases, I would recommend explicitly calling the ToString method, to make it clear to people reading your code what's going on.
Edit: since this answer was accepted, I thought I should also mention that you should make your ToString() method an override, not a new. This will result in the normally-expected behavior, which is what I described above.

Redundant ToString code?

I was wondering :
writing this code :
DataRow[] g = new DataRow[1] ;
var t=new StringBuilder().AppendFormat("{0}", g[0]["aaa"].ToString());
Resharper shows it like : ( notice the gray )
3 questions please
1) removing ToString() , how will the object will output its display string without calling the removed ToString() ?
2) does it suggest to remove it because he already calls it internally ? or because of another reason ?
3) not removing ToString() , will it call it twice ?
Yes, it is redundant because AppendFormat (like String.Format) internally already converts it to a string and String.ToString is always redundant.
Actually it uses the ICustomFormatter.Format method on every provided parameter.
It's also redundant in terms of useless. So even if no work needs to be done multiple times(AppendFormat will not try to convert a string to a string), it is pointless since AppendFormat would do it anyway. Hence resharper tries to simplify your code here.
You may want to see: Composite Formatting
Processing Order
Each value in the parameter list that corresponds to a format item is
converted to a string by performing the steps in the following list.
If any condition in the first three steps is true, the string
representation of the value is returned in that step, and subsequent
steps are not executed.
If the value to be formatted is null, an empty string ("") is returned.
If the composite formatting method includes a parameter of type IFormatProvider that also implements the ICustomFormatter interface,
the value is passed to the ICustomFormatterFormat method.
If the value implements the IFormattable interface, its IFormattableToString method is called.
The type's ToString method, which is either overridden or inherited from the Object class, is called.
Whereas DataRow seems to inherit from System.Object and doesn't implmenet IFormatProvider or IFormattableToString, so I believe, its ToString method is called to get the string representation internally, and having explicit .ToString is considered redundant.

ToString on null string

Why does the second one of these produce an exception while the first one doesn't?
string s = null;
MessageBox.Show(s);
MessageBox.Show(s.ToString());
Updated - the exception I can understand, the puzzling bit (to me) is why the first part doesn't show an exception. This isn't anything to do with the Messagebox, as illustrated below.
Eg :
string s = null, msg;
msg = "Message is " + s; //no error
msg = "Message is " + s.ToString(); //error
The first part appears to be implicitly converting a null to a blank string.
because you cannot call instance method ToString() on a null reference.
And MessageBox.Show() is probably implemented to ignore null and print out empty message box.
It is because MessageBox.Show() is implemented with pinvoke, it calls the native Windows MessageBox() function. Which doesn't mind getting a NULL for the lpText argument. The C# language has much stricter rules for pure .NET instance methods (like ToString), it always emits code to verify that the object isn't null. There's some background info on that in this blog post.
As this question ranks quite high on Google for a search for "c# toString null", I would like to add that the Convert.ToString(null) method would return an empty a null string, which is ignored by the messagebox.
However, just to reaffirm the other answers, you can use string.Concat("string", null) in this example.
Edit - modified answer in line with HeyJude's comment below. As pointed out, a method like Convert.ToString(null).Length will throw an exception.
Behind the scenes concat is being called in your follow up question / update E.g
string snull = null;
string msg = "hello" + snull;
// is equivalent to the line below and concat handles the null string for you.
string msg = String.Concat("hello", snull);
// second example fails because of the toString on the null object
string msg = String.Concat("hello", snull.ToString());
//String.Format, String.Convert, String.Concat all handle null objects nicely.
You are trying to execute the ToString() method on a null. You need a valid object in order to execute a method.
The .show function must have null checking and handle it.
Because, the second call is expecting an object of "s" to satisfy a ToString() method request. so, before .Show() is called, the s.ToString() would failed with an attempt to call a method.
Interestingly, While .Show() is implemented correctly, many such methods expect non null instances to be passed in. Usually, that is when you use a NullObject pattern so that the caller should not have to deal with this kind of behavior.
Probably the Show method handles a null value and just shows nothing.
The second use of s - s.ToString() fails because you there is no ToString method to run.
ToString() can't operate on null reference of s vairable
The shortest way
obj?.ToString()
Another correct ways
obj?.ToString() ?? string.Empty
obj?.ToString() ?? "default string value"
https://www.informit.com/articles/article.aspx?p=2421572

Why is there an overload for String.Concat() which accepts one parameter in .NET

Noticed this today when a patch was submitted with the following line:
lblCompletionTime.Text = String.Concat(trainingSkill.EndTime.ToLocalTime())
I can understand why the contributor used that syntax as above line concatenated two strings to form a multi-part date/time string.
Is there some hidden reason for having a single parameter overload of String.Concat() or was it included for "completeness" by the language designers.
I have replaced the line with:
lblCompletionTime.Text = trainingSkill.EndTime.ToLocalTime().ToString(CultureInfo.CurrentCulture)
Which has the same output.
String.Concat(Object) gives you String.Empty when you pass null; ToString would crash with a null pointer exception.
I agree that it doesn't make much sense especially considering the fact that this is the implementation:
public static string Concat(object arg0)
{
if (arg0 == null)
{
return Empty;
}
return arg0.ToString();
}
But it does validate that the argument isn't null so I guess that is something. Still you aren't concatenating anything so I think that this method could have been called
String.ToStringSafe(Object obj) { }
or something similar to better express what the function actually does.
According to MSDN, String.Concat(object)
Creates the String representation of a
specified object.
By looking at the documentation of String.Concat(object), the only advantage I see is that it accepts a null and returns an empty string, which can be an advantage when compared with object.ToString() which would throw a NullReferenceException.
In your example it doesn't help because if trainingSkill.EndTime is null the program will break when invoking ToLocalTime.
I preffer your correction, but I think there's no need for passing CultureInfo.CurrentCulture as a parameter since it is the default behaviour of DateTime.ToString()
In C# it may have little value (aside from the automatic empty string for a null value).
In .Net in general, I could this method signature being very useful in a functional language.
Using String.Concat(Object) to convert an object to a string is the behavior that overload of the function was designed for.
String.Concat Method (Object)
Creates the String representation of a specified object.

Categories