domn1995/dunet

Idea: Friendly use of ToString()

harrison314 opened this issue · 4 comments

For example, I have a union defined like this:

    [Dunet.Union]
    public partial record BussinesLogicResult<T>
    {
        public partial record Ok(T Value);
        public partial record EntityNotFound();
        public partial record UnauthorizedAccess();
    }

Well, I would like to override the ToString() method like this:

    [Dunet.Union]
    public partial record BussinesLogicResult<T>
    {
        public partial record Ok(T Value);
        public partial record EntityNotFound();
        public partial record UnauthorizedAccess();

        public override string ToString()
        {
            return this.Match<string>(ok => ok.Value.ToString(),
                entityNotFound => "Not found.",
                unauthorizedAccess => "Unauthorized access.");
        }
    }

However, this has no effect as a result, because the records are implicitly override ToString() method. And it is necessary to override ToString() separately for each record.

My idea is that if the ToString() method is found in the base record, the public override string ToString() => base.ToString(); code will be generated in the uion members (children).

Hey, thanks for contributing your idea!

I'm not sure if source generation is the right approach to this problem because it's really inflexible and only a little bit less code than overriding the ToString() methods yourself like this:

[Dunet.Union]
public partial record BussinesLogicResult<T>
{
    public partial record Ok(T Value)
    {
        public override string ToString() => Value.ToString();
    }

    public partial record EntityNotFound
    {
        public override string ToString() => "Not found.";
    }
        
    public partial record UnauthorizedAccess
    {
        public override string ToString() => "Unauthorized access.";
    }
}

Another simple alternative that I also think is better than source generation is creating your own extension method like this:

public static class BusinessLogicResultExtensions
{
    public static string ToStr<T>(this BusinessLogicResult<T> result) => 
        result.Match(
            ok => ok.Value.ToString(),
            entityNotFound => "Not found.",
            unauthorizedAccess => "Unauthorized access."
        );
}

I'm not sure if source generation is the right approach to this problem because it's really inflexible and only a little bit less code than overriding the ToString() methods yourself like this:

That's not pretty code.

As a result, the simplicity and ease of use of Dunet is lost.

Another simple alternative that I also think is better than source generation is creating your own extension method like this:

I am talking about the ToString method because it is implicitly used in many places in C# applications (logging, debug view, orher recorded,...).

Did some more research and if you seal the override in the union declaration, it should work exactly as intended. Here's an example:

using Dunet;
using static BusinessLogicResult<int>;

BusinessLogicResult<int> ok = new Ok(42);
BusinessLogicResult<int> notFound = new EntityNotFound();
BusinessLogicResult<int> unauthorized = new UnauthorizedAccess();

PrintResult(ok); // Prints "42"
PrintResult(notFound); // Prints "Not found."
PrintResult(unauthorized); // Prints "Unauthorized access."

static void PrintResult<T>(BusinessLogicResult<T> result) => Console.WriteLine(result.ToString());

[Union]
public partial record BusinessLogicResult<T>
{
    public partial record Ok(T Value);

    public partial record EntityNotFound();

    public partial record UnauthorizedAccess();

    public sealed override string ToString() =>
        Match(
            ok => ok.Value.ToString(),
            entityNotFound => "Not found.",
            unauthorizedAccess => "Unauthorized access."
        );
}

Well thank you. I didn't know about this solution.