Question

If I am creating a class which fundamentally contains a string message, but which also includes useful data associated with the string message, is there any reason I should override the ToString() method rather than defining a cast to string to get the object's internal string message?

Example, I have a Message object called msg whose text == "Hello" but which also contains information about the source of the text. I want Console.WriteLine(msg); to output "Hello". Should I override ToString() or define a cast to string?

Was it helpful?

Solution

You should override the ToString method.

Firstly: Console.WriteLine accepts object and calls ToString method from it.

Secondly: Sometime in the future you may need to create class, derived from the Message. Let's look at this:

using System;
using System.IO;

namespace Namespace
{
    class StringCastBase
    {
        public static explicit operator string(StringCastBase o)
        {
            return "string cast base";
        }
    }

    class StringCastDerived : StringCastBase
    {
        public static explicit operator string(StringCastDerived o)
        {
            return "string cast derived";
        }
    }

    class ToStringOverridenBase
    {
        public override string ToString()
        {
            return "ToString overriden base";
        }
    }

    class ToStringOverridenDerived : ToStringOverridenBase
    {
        public override string ToString()
        {
            return "ToString overriden derived";
        }
    }

    class Programm
    {
        public static void Main()
        {
            StringCastBase scb = new StringCastBase();
            Console.WriteLine((string)scb);

            StringCastBase scd = new StringCastDerived();
            Console.WriteLine((string)scd);

            ToStringOverridenBase tsob = new ToStringOverridenBase();
            Console.WriteLine(tsob);

            ToStringOverridenBase tsod = new ToStringOverridenDerived();
            Console.WriteLine(tsod);
        }
    }
}

The output will be

string cast base

string cast base

ToString overriden base

ToString overriden derived

Since the static type of scd is StringCastBase, the StringCastBase's conversion method will be called (even when dynamic type is not StringCastBase). Using virtual method ToString solves this problem.

OTHER TIPS

I would say the best technique would be to have your class implement a read-only property called (for example) 'Text' which provides the main string. You've said that the class contains additional information beyond the message text - so really, getting the text means extracting that data from your class. And that's exactly what a property is for!

As a convenience, I would probably also override ToString() - in order to (a) assist debugging, and (b) ensure that something meaningful is returned if ToString() is called by other methods - such as Console.WriteLine() - as soon has mentioned in his answer. Bear in mind that the purpose of ToString() is to provide a string representation of the object, so you might consider whether you want ToString() to only return the main text, or whether you want it to give some indication of the other information the object contains too.

I would definitely not use a cast in this situation. It's semantically wrong for what you are doing. A cast implies you are converting the data from one type to another type. But that's not what you are doing - you're looking to extract a particular piece of data (the main text) from the class. Using a cast for that purpose could be confusing to other developers.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top