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.
Related
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.
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.
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.
whats the difference in the two string methods below?
string str1 = dr["RAGStatusCID"].ToString();
string str2 = (string)dr["Description"];
This will depend on what dr is. The first invokes the ToString method that each object could override on the indexer of the dr["RAGStatusCID"]. The second casts the dr["Description"] variable to a string.
If we use our telepathic skills and suppose that dr is a SqlDataReader then the two expression do pretty much the same thing except that the cast might throw an exception at runtime if the Description column is not a string.
You haven't mentioned the type of dr or what it's indexer operation returns, but ostensibly, these are two very different operations.
The first invokes the get indexer of dr and calls the ToString() method on the returned reference, allowing the object that reference refers to to provide a string representation of it's data. The generial intent of this is to allow the object itself to return a meaningful representation of itself as a string.
The second call attempts to cast the reference returned by the indexer to System.String. The object returned must either be an instance of System.String or must be a type that the compiler can invoke a custom conversion operator on. Here, the intent is to ensure that the object returned can be treated as an instance of System.String. You can read more about conversions (including user-defined ones) on MSDN.
First one calls the method that returns the string. Someone has to implement ToString method. Second one is just unboxing.
string str1 = dr["RAGStatusCID"].ToString();
This calls the .ToString() method on the object returned from the dr["RAGStatusCID"] call. It is guaranteed to return a string or null.
string str2 = (string)dr["Description"];
This attempts to cast the object returned by dr["Description"] to a string. If the object returned is not a string, then an exception is thrown.
in short, .toString() is a method, just like any other, (String) is a cast, a language construct used to treat one data type as another, compatible type.
Now for some detail:
.toString() is a method, just like any other method you may encounter. Its often thought to be a 'special' method in some way, but it isnt really, all it does is return a string. because its a member of the base Object type, it can be relied upon to be available in every object. For this reason it is generally used to provide a textual representation of the object of which it is member. By default, in c# this is the name of the type of the object. It is often desirable to override this method to provide a more meaningful name, but all it needs to do is return a string, this can be any string you like.
As noted before, theres nothing special about it, and you could just as easily have methods called ToInt(), ToDouble(), and ToChar() to provide the same functionality for there respective types.
Casting is a language construct, this means its built into the language and is implemented specifically for that language. It is used to enable compatible but different types to be used in different locations without the need for an explicit conversion.
xxx.ToString() calls a method on that object to convert it into a string object. (string)xxx assumes that the type of the object is already a string and simply performs a cast on the existing object. So in the first case a conversion happens, in the second it's just identifying the type explicitly.
To put it more succinctly, if in your example RagStatusCID is an integer and you attempted to call (string)dr["RagStatusCID"] you would get an exception because the type is not a string, it's an int. Calling .ToString() performs a conversion and the output is a string.
(string) is a casting operation. .ToString() is a method that is inherited from the Object class. Everything has a .ToString(), but not everything has a (string). Additionally certain objects will cast to a string different than the one .ToString() outputs.
I don't know if it is correct for C# but it probably is, so:
(String)myinstance calls implicitly the .toString() implementation of myinstance's class
if you have a class like this:
class User
{
private integer userId;
private integer userName;
... some code here...
public toString()
{
return "Username: " + this.userName + " (" + this.userId + ")";
}
}
with the method toString you are defining what (String)instance casting will do
User myuser = new User("Alex", 22);
String myuserdump = (String)myuser;
print(myuserdump);
will print "Username: Alex (22)"
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.