Console.WriteLine
outputs a string
to the console. But the argument can be any object, not just a string. So if the argument is some other type (like a byte array) then it calls the object's ToString()
method and writes that out. This always works because everything inherits from object
and therefore every object has a ToString()
method.
But more often than not, that ToString()
method isn't overridden. So it just executes object.ToString()
which returns the name of the type of the object.
That's why if you do this:
var byteArray = new byte[] { };
Console.WriteLine(byteArray);
You get this:
System.Byte[]
You probably want to see the individual values, but ToString()
doesn't return that. It just returns the name of the type. So if you wanted to actually output the values for each byte you would have to do that explicitly:
foreach(var b in byteArray)
Console.WriteLine(b);
Now you're not calling WriteLine(object)
. You're calling WriteLine(int)
(because byte
can be implicitly converted to int
). An int
can be represented as a string
, so now it knows how to write the value to the console.
Just for fun, and to illustrate the concept, you could write a class like this:
public class MyBytes : List<byte>
{
public override string ToString()
{
return "These are my bytes:"
+ Environment.NewLine
+ string.Join(Environment.NewLine, this);
}
}
It inherits from List<Byte>
and overrides ToString()
. If you create an instance of MyBytes
, populate it, and write it to the console:
var byteArray = new byte[] { 1, 2, 3 };
var myBytes = new MyBytes();
myBytes.AddRange(byteArray);
Console.WriteLine(myBytes);
You'll see that it calls your overridden ToString()
method:
These are my bytes:
1
2
3
That's just for illustration. Sometimes if we know that we're going to want to output a string representation of a class it makes sense to override ToString()
, but I wouldn't create a whole class just for the purpose of overriding ToString()
.